AtCoder Grand Contest 018 F - Two Trees

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 Ai. Here, Ai=−1 if Vertex i is the root of the first tree. In the second tree, the parent of Vertex i is Vertex Bi. Here, Bi=−1 if Vertex i is the root of the second tree.

Snuke would like to construct an integer sequence of length NX1 , X2 ,  , XN, that satisfies the following condition:

  • For each vertex on each tree, let the indices of its descendants including itself be a1 , a2 , ak. Then, abs(Xa1+Xa2++Xak)=1 holds.

Determine whether it is possible to construct such a sequence. If the answer is possible, find one such sequence.

Constraints

  • 1N105
  • 1AiN, if Vertex i is not the root in the first tree.
  • Ai=−1, if Vertex i is the root in the first tree.
  • 1BiN, if Vertex i is not the root in the second tree.
  • Bi=−1, if Vertex i is the root in the second tree.
  • Input corresponds to valid rooted trees.

Input

Input is given from Standard Input in the following format:

N
A1 A2 .. AN
B1 B2 .. BN

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 X1 , X2 ,  , XN, an integer sequence that satisfies the condition.


Sample Input 1

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

Sample Output 1

Copy
POSSIBLE
1 -1 -1 3 -1

For example, the indices of the descendants of Vertex 3 of the first tree including itself, is 3,1,2. It can be seen that the sample output holds abs(X3+X1+X2)=abs((−1)+(1)+(−1))=abs(−1)=1. Similarly, the condition is also satisfied for other vertices.


Sample Input 2

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

Sample Output 2

Copy
IMPOSSIBLE

In this case, constructing a sequence that satisfies the condition is IMPOSSIBLE.


Sample Input 3

Copy
8
2 7 1 2 2 1 -1 4
4 -1 4 7 4 4 2 4

Sample Output 3

Copy
POSSIBLE
1 2 -1 0 -1 1 0 -1

题意:给两棵有根树,给1到n确定一个点权使得任意一棵子树的点权和的绝对值为1

题解:欧拉回路

首先绝对值为1暗示我们模2为1,所以每个点的奇偶性就确定了,如果矛盾则不合法

否则我们想办法构造一组解:

考虑欧拉回路,在原树上的边不变,如果i的点权是奇数那么i向i+n连一条边,新建一个点,把两个根连起来,最后如果是i到i+n的边则val[i]=1,否则为-1(不存在则为0)

显然这样是符合要求的,画一画就明白了

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
	int x = 0, f = 1, c = getchar();
	for (; !isdigit(c); c = getchar())
		if (c == '-')
			f = -1;
	for (;  isdigit(c); c = getchar())
		x = x * 10 + c - '0';
	return x * f;
}

const int MAXN = 200005;

struct Edge { int p, v, r; };
int n, par[2][MAXN], typ[2][MAXN], rt[2], ans[MAXN], cur[MAXN];
vector <int> adj[2][MAXN];
vector <Edge> G[MAXN];

inline void Addedge(int x, int y) { G[x].pb({y, 0, G[y].size()}), G[y].pb({x, 0, G[x].size() - 1}); }

inline void Dfs(int x, int t)
{
	typ[t][x] = 1;
	for (auto y : adj[t][x])
		Dfs(y, t), typ[t][x] ^= 1;
}

inline void Dfs(int x)
{
	while (cur[x] < G[x].size())
		if (G[x][cur[x]].v)
			cur[x] ++;
		else
		{
			int c = cur[x];
			G[x][c].v = 1;
			G[G[x][c].p][G[x][c].r].v = 1;
			if (x && G[x][c].p == x + n)
				ans[x] = -1;
			else if (x - n && G[x][c].p == x - n)
				ans[x - n] = 1;
			Dfs(G[x][c].p);
		}
}

int main()
{
#ifdef wxh010910
	freopen("data.in", "r", stdin);
#endif
	n = Read();
	for (int i = 1; i <= n; i ++)
		par[0][i] = Read(), rt[0] = par[0][i] == -1 ? i : rt[0], adj[0][par[0][i]].pb(i);
	for (int i = 1; i <= n; i ++)
		par[1][i] = Read(), rt[1] = par[1][i] == -1 ? i : rt[1], adj[1][par[1][i]].pb(i);
	Dfs(rt[0], 0);
	Dfs(rt[1], 1);
	for (int i = 1; i <= n; i ++)
		if (typ[0][i] ^ typ[1][i])
			return puts("IMPOSSIBLE"), 0;
	puts("POSSIBLE");
	for (int i = 1; i <= n; i ++)
		if (~par[0][i])
			Addedge(par[0][i], i);
		else
			Addedge(0, i);
	for (int i = 1; i <= n; i ++)
		if (~par[1][i])
			Addedge(par[1][i] + n, i + n);
		else
			Addedge(0, i + n);
	for (int i = 1; i <= n; i ++)
		if (typ[0][i])
			Addedge(i, i + n);
	Dfs(0);
	for (int i = 1; i <= n; i ++)
		printf("%d%c", ans[i], i == n ? '\n' : ' ');
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值