AGC018F Two Trees
Link
显然对于每个点而言,它在两棵树中的儿子数的奇偶性必须相同。
然后我们将两棵树分别建出来,建一个超级根与两棵树的根相连,并且对于儿子数为奇数的点,将其在两棵树中的点连边。
这个无向图每个点的度数都是偶数,我们找一个Euler回路出来。
对于一个点,如果它的儿子数为偶,那么让它的权值为\(0\)。
否则如果欧拉回路中是从第一棵树走到第二棵树,就让它的权值为\(1\),如果是从第二棵树走到第一棵树,就让它的权值为\(-1\)。
#include<cstdio>
#include<vector>
const int N=600007;
int n,tot=1,head[N],ver[N],next[N],v1[N],v2[N],val[N];
int read(){int x;scanf("%d",&x);return x;}
void add(int u,int v){ver[++tot]=v,next[tot]=head[u],head[u]=tot,ver[++tot]=u,next[tot]=head[v],head[v]=tot;}
void work(int u,int v){if(u==v+n)val[v]=1;if(v==u+n)val[u]=-1;}
void dfs(int u){for(int&i=head[u],v;i;i=next[i])if(!v1[i])v1[i]=v1[i^1]=1,work(u,v=ver[i]),dfs(v);}
int main()
{
n=read();
for(int i=1,x;i<=n;++i) ~(x=read())? v1[x]^=1,v2[x]^=1,add(x,i):add(0,i);
for(int i=1,x;i<=n;++i) ~(x=read())? v1[x]^=1,add(x+n,i+n):add(0,i+n);
for(int i=1;i<=n;++i){if(v1[i])return puts("IMPOSSIBLE"),0;if(!v2[i])add(i,i+n);}
puts("POSSIBLE"),dfs(1);
for(int i=1;i<=n;++i) printf("%d%c",val[i]," \n"[i==n]);
}