把编号抛开来看就是判断两棵树是否同构,之后再随便搞搞把编号对应上去。
判断树的同构用树哈希就好了,把每个节点的信息处理成哈希值,只要两棵树是同构的,以两棵树的重心为根的树只要保证同样形态的儿子节点是按顺序来枚举的,求哈希的时候就可以随便乱搞。判断了树同构之后在两棵树上同时BFS就能够对应出一个P数组。
因为只用一个质数可能会被卡,可以在加入的值中再乘上另一个质数就能够减少出错概率。
#include
#include
#include
#include
#include
using namespace std;
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,x) for(i=la[x];i;i=ne[i])
#define REP(i,x) for(i=LA[x];i;i=NE[i])
#define root {if(!rt1)rt1=x;else rt2=x;}
#define ROOT {if(!RT1)RT1=x;else RT2=x;}
typedef unsigned long long ull;
const int N=1e5+5;
const ull P=63,Q=31;
struct arr{ull s;int x;}d[N],D[N];
ull S[N],tot[N],TOT[N];
int la[N],da[N*2],ne[N*2],sum,rt1,rt2,node[N],dl[N];
int LA[N],DA[N*2],NE[N*2],SUM,RT1,RT2,NODE[N],DL[N];
int n,i,x,y,ans[N],ns,NS;
bool cmp(arr x,arr y){return x.svoid ins(int x,int y){da[++sum]=y;ne[sum]=la[x];la[x]=sum;}
void INS(int x,int y){DA[++SUM]=y;NE[SUM]=LA[x];LA[x]=SUM;}
void gnode(int x,int fa){
int i,mx=0;node[x]=1;
rep(i,x)if(da[i]!=fa)
gnode(da[i],x),mx=max(mx,node[da[i]]),node[x]+=node[da[i]];
if((n-node[x]<=n/2)&&(mx<=n/2)) root;
}
void Gnode(int x,int fa){
int i,mx=0;NODE[x]=1;
REP(i,x)if(DA[i]!=fa)
Gnode(DA[i],x),mx=max(mx,NODE[DA[i]]),NODE[x]+=NODE[DA[i]];
if((n-NODE[x]<=n/2)&&(mx<=n/2)) ROOT;
}
void fill(int x,int fa){
int i;node[x]=1;
rep(i,x)if(da[i]!=fa) fill(da[i],x),node[x]+=node[da[i]];
ns=0;rep(i,x)if(da[i]!=fa) S[++ns]=tot[da[i]];
tot[x]=tot[x]*P+node[x]*Q;
if(!ns) return;sort(S+1,S+ns+1);
fo(i,1,ns) tot[x]=tot[x]*P+S[i]*Q;
}
void FILL(int x,int fa){
int i;NODE[x]=1;
REP(i,x)if(DA[i]!=fa) FILL(DA[i],x),NODE[x]+=NODE[DA[i]];
NS=0;REP(i,x)if(DA[i]!=fa) S[++NS]=TOT[DA[i]];
TOT[x]=TOT[x]*P+NODE[x]*Q;
if(!NS) return;sort(S+1,S+NS+1);
fo(i,1,NS) TOT[x]=TOT[x]*P+S[i]*Q;
}
void bfs(int rt,int fa,int RT,int FA){
int i,l=0,r=1;
dl[1]=rt;DL[1]=RT;
while(l0;rep(i,rt)if(node[da[i]]0;REP(i,RT)if(NODE[DA[i]]1,d+ns+1,cmp);sort(D+1,D+NS+1,cmp);
fo(i,1,ns) r++,dl[r]=d[i].x,DL[r]=D[i].x;
}
}
bool pd(int rt,int RT){
memset(node,0,sizeof(node));
memset(tot,0,sizeof(tot));fill(rt,0);
memset(NODE,0,sizeof(NODE));
memset(TOT,0,sizeof(TOT));FILL(RT,0);
if(tot[rt]!=TOT[RT]) return 0;
bfs(rt,0,RT,0);return 1;
}
int main(){
scanf("%d",&n);
fo(i,1,n-1) scanf("%d%d",&x,&y),ins(x,y),ins(y,x);
fo(i,1,n-1) scanf("%d%d",&x,&y),INS(x,y),INS(y,x);
gnode(1,0);Gnode(1,0);
if(pd(rt1,RT1)||pd(rt1,RT2)||pd(rt2,RT1)||pd(rt2,RT2)){
if(ans[1]==0){
printf("NO\n");return 0;
}
printf("YES\n");
fo(i,1,n) printf("%d ",ans[i]);printf("\n");
return 0;
}
printf("NO\n");
}