[AGC018]F

Time limit : 2sec / Memory limit : 256MB

Problem Statement

There are two rooted trees, each with (N) vertices. The vertices of each tree are numbered (1) through (N). In the first tree, the parent of Vertex (i) is Vertex (A_i). Here, (A_i=−1) if Vertex (i) is the root of the first tree. In the second tree, the parent of Vertex (i) is Vertex (B_i). Here, (B_i=−1) if Vertex i is the root of the second tree.

Snuke would like to construct an integer sequence of length (N), (X_1 , X_2 , … , X_N), that satisfies the following condition:

For each vertex on each tree, let the indices of its descendants including itself be (a_1 , a_2 , …, a_k).Then, (abs(X_{a_1}+X{a_2}+…+X{a_k})=1) holds.
Determine whether it is possible to construct such a sequence. If the answer is possible, find one such sequence.

Constraints

  • (1≤N≤10^5)
  • (1≤A_i≤N), if Vertex (i) is not the root in the first tree.
  • (A_i=−1), if Vertex (i) is the root in the first tree.
  • (1≤B_i≤N), if Vertex (i) is not the root in the second tree.
  • (B_ii=−1), if Vertex (i) is the root in the second tree.
  • Input corresponds to valid rooted trees.

Input

The input is given from Standard Input in the following format:

(N)
(A_1 A_2 .. A_N)
(B_1 B_2 .. B_N)

Output

If it is not possible to construct an integer sequence that satisfies the condition, print IMPOSSIBLE. If it is possible, print POSSIBLE in the first line. Then, in the second line, print (X_1 , X_2 , … , X_N), an integer sequence that satisfies the condition.

Sample Input 1

5
3 3 4 -1 4
4 4 1 -1 1

Sample Output 1

POSSIBLE
1 -1 -1 3 -1

Sample Input 2

6
-1 5 1 5 1 3
6 5 5 3 -1 3

sample output 2

IMPOSSIBLE

题意

给出两棵树,要求给两棵树上相同编号的点赋值,使得每个点的子树权值和的绝对值为1

分析

首先可以给每个点的权值确定奇偶性,如果一点在两棵树上奇偶性不同那么一定不存在合法的构造方案(奇数权值节点有偶数个儿子,偶数权值节点有奇数个儿子)
可以发现,如果构造合法解,可以只用到0,-1,1这三种权值,构造方法如下:
如果一个点的权值为偶数,那么这个点的权值为0
然后开始处理奇数点,每个父亲考虑给自己的儿子两两在新图上连边,表示父亲给儿子分配冲突(-11
如果父亲为偶数点,那么当前父亲子树权值取决于两两匹配后剩下那个儿子的子树权值;否则父亲为奇数点则子树权值取决于当前点的权值
所以在两两连边时,如果有偶数点,相当于拿 决定这个点子树权值的那个奇数点 与另一点连边
易证出新图一定能进行二分图染色(因为不存在奇环),就能得出奇数点的权值


CODE

#include<bits/stdc++.h>
using namespace std;
vector<int>a[101010],b[101010];
int n,root1,root2,doe;
int id[101010],v[101010];
int pre[808080],son[808080],now[101010];
void add(int x,int y)
{
	++doe;
	pre[doe]=now[x];
	now[x]=doe;
	son[doe]=y;
}
void connect(int x,int y)
{
	x=id[x]; y=id[y];
	add(x,y); add(y,x);
}

void dfs1(int x)
{
	int len=a[x].size();
	for (int i=0;i<len;++i)
	{
		int y=a[x][i];
		dfs1(y);
		if (i%2==1) connect(a[x][i],a[x][i-1]);
	}
	if (len%2==1) id[x]=id[a[x][len-1]];
}
void dfs2(int x)
{
	int len=b[x].size();
	for (int i=0;i<len;++i)
	{
		int y=b[x][i];
		dfs2(y);
		if (i%2==1) connect(b[x][i],b[x][i-1]);
	}
	if (len%2==1) id[x]=id[b[x][len-1]];
}
void col(int x)
{
	int p=now[x];
	while (p)
	{
		int y=son[p];
		if (v[y]==0)
		{
			v[y]=-v[x];
			col(y);
		}
		p=pre[p];
	}
}
int main()
{
	freopen("F.in","r",stdin);
	freopen("F.out","w",stdout);

	scanf("%d",&n);
	int x;
	for (int i=1;i<=n;++i)
	{
		scanf("%d",&x);
		if (x==-1) root1=i;
		else a[x].push_back(i);
	}
	for (int i=1;i<=n;++i)
	{
		scanf("%d",&x);
		if (x==-1) root2=i;
		else b[x].push_back(i);
	}
	for (int i=1;i<=n;++i) if (a[i].size()%2 != b[i].size()%2)
	{
		printf("IMPOSSIBLE
");
		return 0;
	}
	
	for (int i=1;i<=n;++i) id[i]=i;
	dfs1(root1);
	for (int i=1;i<=n;++i) id[i]=i;
	dfs2(root2);
	for (int i=1;i<=n;++i) if (a[i].size()%2==0 && v[i]==0)
	{
		v[i]=1;
		col(i);
	}
	printf("POSSIBLE
");
	for (int i=1;i<=n;++i) printf("%d ",v[i]);
	printf("
");
	return 0;
}
原文地址:https://www.cnblogs.com/dogcdt/p/9549256.html