In the world waiting to be lit

【AGC018F】Two Trees。

非常难的题目,爱来自【数据删除】。

先考虑对着题目进行大观察,我们声称存在一种有效的方式,满足 \(X \in \{-1,0,1\}\)。

考虑模 \(2\) 意义下的题目,发现 \(u\) 节点的值相当于 \(s_u = x_u + \sum s_v\)。而在模 \(2\) 意义下,\(s_v = 1\)。因此这个东西本质是在判度数的奇偶性啊。因此我们不难找到一个成立的必要条件:在 \(a,b\) 树中,都满足 \(deg_u\) 的奇偶性相等。

接下来的构造会说明这个是充分的。看到这种状物,不妨想欧拉回路,但是我们的度数是有奇数的,不好,因此考虑对于度数为奇数的点,两树之间进行连边。然后跑欧拉回路,如果是从左往右的,\(x_u = 1\),否则为 \(-1\)。当然,如果不需要横叉边,那么 \(x_u=0\)。

证明这个为什么是对的。欧拉回路可以分成若干环,刻画环对于某个点的影响。显然的,如果从儿子出发,从儿子/横叉边回来不会影响。从儿子出发,父亲回来,或者从横叉边/父亲出发,从父亲/横叉边回来会造成 \(-1\) 或者 \(+1\) 的贡献,但是这样的情况只会有 \(1\) 次。

Code

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int N = 3e5 + 10;
int n;
int eu[N],ev[N],f[N],cnt,deg[N],used[N];
vector<int> G[N];
void add(int u,int v,int w){
	cnt ++ ;
	deg[u] ++ ;
	deg[v] ++ ;
	eu[cnt] = u,ev[cnt] = v,f[cnt] = w;
	G[u].push_back(cnt);
	G[v].push_back(cnt);
	return ;
}
int w[N];
void dfs(int u){
	while(!G[u].empty()){
		int i = G[u].back();
		G[u].pop_back();
		if(used[i]) continue;
		int v = eu[i] ^ ev[i] ^ u;
		used[i] = 1;
		if(f[i]){
			if(u < v) w[u] = 1;
			else w[v] = -1;
		}
		dfs(v);
	}
	return ;
}
int main(){
	IOS;
	cin >> n;
	for(int i=1;i<=n;i++){
		int x;
		cin >> x;
		if(x == -1) x = 2 * n + 1;
		add(i,x,0);
	}
	for(int i=1;i<=n;i++){
		int x;
		cin >> x;
		if(x == -1) x = n + 1;
		add(i+n,x+n,0);
	}
	for(int i=1;i<=n;i++)
		if(deg[i] % 2 != deg[i+n] % 2){
			cout << "IMPOSSIBLE";
			return 0;
		}
	cout << "POSSIBLE\n";
	for(int i=1;i<=n;i++)
		if(deg[i] % 2 == 1)
			add(i,i+n,1);
	dfs(1);
	for(int i=1;i<=n;i++)
		cout << w[i] << " ";
	return 0;
}
posted @ 2026-09-24 09:59  WinterXorSnow  阅读(10)  评论(0)    收藏  举报