EOJ3652 乘法还原

EOJ3652 乘法还原

题目链接

https://acm.ecnu.edu.cn/problem/3652/

题目大意

两个序列,分别是 $\{a_i\}$ 和 $\{b_i\}$,随后用这两个序列构造了一个表达式 $(x_{a_1} + … + x_{a_m})(x_{b_1} + … + x_{b_n})$。告诉你这个表达式的展开式,让你还原出这两个序列。

题目分析

对于给出的展开式中,如果有两项相同的话,说明 $a$ 和 $b$ 中都有这一项,可以直接将其加入 $a$ 和 $b$ 中。对于其他的,可使用 $DFS$ 对其进行染色,任何一个连边的都不属于同样的集合。注意有可能只有一边有未出现的项,需要单独处理。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <map>

using namespace std;

const int maxn = 1e5 + 5;

int n;

vector <int> a;
vector <int> b;

vector <int> ansa;
vector <int> ansb;

map <int, bool> m;

map <int, vector <int> > e;
map <int, bool> v;

int read(){
	int x;
	scanf("%d", &x);
	return x;
}

bool check(){
	if(ansa.size() != ansb.size()){
		return ansa.size() > ansb.size();
	}else{
		for(int i=0;i<ansa.size();i++){
			if(ansa[i] != ansb[i]){
				return ansa[i] > ansb[i];
			}
		}
	}
	
	return false;
}

int addedge(int x, int y){
	e[x].push_back(y);
	e[y].push_back(x);
	
	return 0;
}

int dfs(int x, int d){
	int i, j;
	int y;
	v[x] = true;
	
	if(d == 0){
		ansa.push_back(x);
	}else{
		ansb.push_back(x);
	}
	
	for(i=0;i<e[x].size();i++){
		y = e[x][i];
		if(!v[y]){
			dfs(y, !d);
		}
	}
	
	return 0;
}

int main(){
	int i, j;
	int x, y;
	int root = 0;
	int cnt = 0;
	
	n = read();
	
	for(i=1;i<=n;i++){
		x = read();
		y = read();
		
		if(x == y){
			ansa.push_back(x);
			ansb.push_back(y);
			m[x] = true;
			cnt++;
		}else{
			a.push_back(x);
			b.push_back(y);
		}
	}
	
	for(i=0;i<a.size();i++){
		x = a[i];
		y = b[i];
		if(m[x] or m[y]){
			continue;
		}else{
			addedge(x, y);
			root = x;
		}
	}
	
	if(root)dfs(root, 0);
	
	if(ansa.size() == cnt){
		for(i=0;i<a.size();i++){
			x = a[i];
			y = b[i];
			if(!m[x]){
				ansb.push_back(x);
				m[x] = true;
			}else if(!m[y]){
				ansb.push_back(y);
				m[y] = true;
			}
		}
	}
	
	sort(ansa.begin(), ansa.end());
	sort(ansb.begin(), ansb.end());
	
	if(check()){
		swap(ansa, ansb);
	}
	
	printf("%d %d\n", ansa.size(), ansb.size());
	
	for(i=0;i<ansa.size();i++){
		printf("%d ", ansa[i]);
	}
	printf("\n");
	
	for(i=0;i<ansb.size();i++){
		printf("%d ", ansb[i]);
	}
	printf("\n");
	
	return 0;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据