题目
有一棵树。树上的点有2种颜色,两个人轮流选择一个白色的点,将其到根的路径上的点
全部染黑。不能操作者输。
开始树上的节点并非全白。
水法
这并不是题解。但是我从水法中学到了一点东西。
考虑只保留白色的点,重新建树。会得到一个森林。
考虑一个点的
所以,选择
然后将这些
然后再去
如果森林中所有根节点的
否则,计算与 根到某个点的路径上的点 有边相连的点(根到某个点的路径上的点)的
心得
重新说一遍:
游戏→子游戏,求
状态→子状态,求
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100010
#define LL long long
#define P(a) putchar(a)
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
struct note{
int to,next;
};note edge[N*2];
int tot,head[N];
int c[N];
int i,j,k,l,n,m;
int nim;
int fa[N],Fa[N],ans[N];
int o[N],cnt[N],CNT;
int sg[N];
int u,v,X;
int read(){
int fh=1,rs=0;char ch;
while((ch<'0'||ch>'9')&&(ch^'-'))ch=getchar();
if(ch=='-')fh=-1,ch=getchar();
while(ch>='0'&&ch<='9')rs=(rs<<3)+(rs<<1)+(ch^'0'),ch=getchar();
return fh*rs;
}
void write(int x){
if(x>9)write(x/10);
P(x%10+'0');
}
void lb(int x,int y){
edge[++tot].to=y;
edge[tot].next=head[x];
head[x]=tot;
}
void dfs(int x,int y){
if(!c[x])Fa[x]=y;
int i;
for(i=head[x];i;i=edge[i].next)
if(edge[i].to^fa[x]){
fa[edge[i].to]=x;
if(c[x])dfs(edge[i].to,y);
else dfs(edge[i].to,x);
}
}
void check(int x){
int i;
for(i=head[x];i;i=edge[i].next)k^=sg[edge[i].to];
cnt[k]=CNT;
for(i=head[x];i;i=edge[i].next){
k^=sg[edge[i].to];
check(edge[i].to);
k^=sg[edge[i].to];
}
for(i=head[x];i;i=edge[i].next)k^=sg[edge[i].to];
}
void dg2(int x){
int i;
for(i=head[x];i;i=edge[i].next)k^=sg[edge[i].to];
if(!k)ans[++ans[0]]=x;
for(i=head[x];i;i=edge[i].next){
k^=sg[edge[i].to];
dg2(edge[i].to);
k^=sg[edge[i].to];
}
for(i=head[x];i;i=edge[i].next)k^=sg[edge[i].to];
}
void dg(int x){
int i;
if(!o[x]){
sg[x]=1;
return;
}
for(i=head[x];i;i=edge[i].next)
if(edge[i].to^Fa[x])
dg(edge[i].to);
X=x;
CNT++;
k=0;
check(x);
for(sg[x]=0;cnt[sg[x]]==CNT;sg[x]++);
}
int main(){
freopen("combat.in","r",stdin);
freopen("combat.out","w",stdout);
n=read();
fo(i,1,n)c[i]=read();
fo(i,1,n-1){
u=read();v=read();
lb(u,v);lb(v,u);
}
dfs(1,0);
memset(edge,0,sizeof(edge));
memset(head,0,sizeof(head));
tot=0;
fo(i,2,n)if(Fa[i]){
lb(Fa[i],i);
o[Fa[i]]++;
}
nim=0;
fo(i,1,n)if(!c[i]&&!Fa[i]){
dg(i);
nim^=sg[i];
}
if(!nim)printf("-1");
else{
fo(i,1,n)if(!Fa[i]&&!c[i])lb(0,i);
k=0;
dg2(0);
sort(ans+1,ans+ans[0]+1);
fo(i,1,ans[0])if(ans[i])write(ans[i]),P('\n');
}
return 0;
}