fastle
垆边人似月 皓腕凝霜雪
/*
考虑直接使用暴力来算的话   SG[i]表示以i为根的子树的SG值, 然后考虑枚举删除那个子树节点, 然后求拆成的树的sg异或值, 求mex即可 复杂度三次方

然后考虑尝试 整体来做 发现对于每次子树的合并, 每棵子树种的sg值相当是异或了其他的所有子树

而这个东西显然是可以用 线段树合并来维护的

最后找出所有sg不为0的点即可

*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#define ll long long
#define M 100010
#define mmp make_pair
using namespace std;
int read() {
	int nm = 0, f = 1;
	char c = getchar();
	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
	return nm * f;
}
int cor[M], cov[M * 60], laz[M * 60], ls[M * 60], rs[M * 60], rt[M], n, sg[M], cnt, ans[M], tot;
vector<int> to[M];

void add(int &now, int v, int deep) {
	if(deep <= -1) return;
	if(v & (1 << deep)) swap(ls[now], rs[now]);
	laz[now] ^= v;
}

void pushdown(int now, int deep) {
	if(!laz[now] || !now) return;
	add(ls[now], laz[now], deep - 1);
	add(rs[now], laz[now], deep - 1);
	laz[now] = 0;
}

int merge(int now, int last, int deep) {
	if(!now || !last) return now | last;
	if(deep == -1) {
		cov[now] |= cov[last];
		return now;
	}
	pushdown(now, deep), pushdown(last, deep);
	ls[now] = merge(ls[now], ls[last], deep - 1);
	rs[now] = merge(rs[now], rs[last], deep - 1);
	cov[now] = cov[ls[now]] && cov[rs[now]];
	return now;
}

void insert(int &now, int v, int deep) {
	if(!now) now = ++cnt;
	if(deep == -1) {
		cov[now] = 1;
		return;
	}
	if(v & (1 << deep)) insert(rs[now], v, deep - 1);
	else insert(ls[now], v, deep - 1);
}

int mex(int now, int deep) {
	if(!now || deep == -1) return 0;
	pushdown(now, deep);
	if(!cov[ls[now]]) return mex(ls[now], deep - 1);
	else return (1 << deep) + mex(rs[now], deep - 1);
}

void dfs(int now, int fa) {
	int tmp = 0;
	for(int i = 0; i < to[now].size(); i++) {
		int vj = to[now][i];
		if(vj == fa) continue;
		dfs(vj, now);
		tmp ^= sg[vj];
	}
	if(!cor[now]) insert(rt[now], tmp, 17);
	for(int i = 0; i < to[now].size(); i++) {
		int vj = to[now][i];
		if(vj == fa) continue;
		add(rt[vj], tmp ^ sg[vj], 17);
		rt[now] = merge(rt[now], rt[vj], 17);
	}
	sg[now] = mex(rt[now], 17);
}

void get(int now, int fa, int anss) {
	for(int i = 0; i < to[now].size(); i++) {
		int vj = to[now][i];
		if(vj == fa) continue;
		anss ^= sg[vj];
	}
	if(anss == 0 && !cor[now]) ans[++tot] = now;
	for(int i = 0; i < to[now].size(); i++) {
		int vj = to[now][i];
		if(vj == fa) continue;
		get(vj, now, anss ^ sg[vj]);
	}
}


int main() {
	n = read();
	for(int i = 1; i <= n; i++) cor[i] = read();
	for(int i = 1; i < n; i++) {
		int vi = read(), vj = read();
		to[vi].push_back(vj);
		to[vj].push_back(vi);
	}
	dfs(1, 0);
	get(1, 0, 0);
	if(tot) {
		sort(ans + 1, ans + tot + 1);
		for(int i = 1; i <= tot; i++) cout << ans[i] << '\n';
	} else puts("-1");
	return 0;
}




posted on 2019-03-14 22:35  fastle  阅读(95)  评论(0编辑  收藏  举报