AT2675 Two Trees
题目描述
给你两棵树,让你求出满足令两棵树所有子树和的绝对值为1,让你构造一组情况,如果不能则输出IMPOSSIBLE。
算法分析
先观察每个点的奇偶性,如果这两棵树对应值连奇偶性都不同,那肯定是不可能的。如果可能的话,跑一遍欧拉回路,如果这个点是偶点则肯定是0,如果是奇点的话,如果该点是指向第二棵树的,则为-1,否则是1。
个人感觉欧拉回路更像是一种配对的过程,是-1,1更均匀的分散看。
注:欧拉回路是一定要优化一下否则肯定会gg
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=110000;
int a[N],b[N],root1,root2,p[N*2],h[N*2],num,n,ans[N*2],f[N*2];
bool flag[N],flag1;
struct node{
int x,y,next,k;
bool flag;
}data[N*10];
void link(int x,int y){
++num;
data[num].x=x;
data[num].y=y;
data[num].next=h[x];
data[num].k=num+1;
data[num].flag=true;
h[x]=num;
++num;
data[num].x=y;
data[num].y=x;
data[num].next=h[y];
data[num].k=num-1;
data[num].flag=true;
h[y]=num;
p[x]++;
p[y]++;
}
void dfs1(int x){
for(int &i=h[x];i!=-1&&i!=0;i=data[i].next){
int v=data[i].y;
if(!data[i].flag)continue;
if(x<=n&&v<=n){f[x]++;f[v]--;}
if(flag1&&x==root1&&v==root2){f[x]++;f[v]--;flag1=false;}
if(flag1&&x==root2&&v==root1){f[x]++;f[v]--;flag1=false;}
data[i].flag=false;
data[data[i].k].flag=false;
dfs1(v);
}
}
int main(){
scanf("%d",&n);
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]!=-1)link(a[i],i);
else root1=i;
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
if(b[i]!=-1)link(b[i]+n,i+n);
else root2=i+n;
}
link(root1,root2);flag1=true;
for(int i=1;i<=n;i++){
if((p[i]%2)!=(p[i+n]%2)){
printf("IMPOSSIBLE\n");
return 0;
}else if(p[i]%2==1)link(i,i+n);
}
printf("POSSIBLE\n");
dfs1(root1);
for(int i=1;i<=n;i++)printf("%d ",f[i]);
return 0;
}