nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上。另一天nodgd更无聊,就又画了一张。
这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到n进行了编号,即每棵树有n个节点。
如果存在一个1到n的排列p1p2…pn,对于第一幅图中的任意一条边(u,v),在第二幅图中都能找到一条边(pu,pv),则认为这两幅图中的树是一样的。
树的哈希版子题,
(写得越猎奇越好)
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define efo(i,q) for(int i=A[E][q];i;i=B[E][i][0])
using namespace std;
typedef long long LL;
typedef LL Uin;
const int N=200500;
const Uin h2mo=1010003;//23 67
const Uin h1mo=4988741;//23 67
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m,ans;
int B[4][2*N][2],A[4][N],B0[4],bv[4][N];
int Si1[N],Sz;
Uin Si[2][N];
int d[2][N];
int en;
int Ans[N],As[N];
struct qqww
{
Uin h1,h2;
Uin sh1,sh2;
Uin z1,z2;
int i,k;
}p[2][N],p1[N],p2[N];
void link(int I,int q,int w)
{
bv[I][q]++;bv[I][w]++;
B[I][++B0[I]][0]=A[I][q],A[I][q]=B0[I],B[I][B0[I]][1]=w;
if(I<2)B[I][++B0[I]][0]=A[I][w],A[I][w]=B0[I],B[I][B0[I]][1]=q;
}
int FDz(int E,int q,int fa)
{
Si1[q]=1;
int mx=0;
efo(i,q)if(B[E][i][1]!=fa)Si1[q]+=FDz(E,B[E][i][1],q),mx=max(mx,Si1[B[E][i][1]]);
mx=max(mx,n-Si1[q]);
if(mx0]=1]=q;
}else if(mx==Sz)d[E][++d[E][0]]=q;
return Si1[q];
}
int dffffff(int E,int q,int fa)
{
Si[E][q]=1;
int mx=0;
efo(i,q)if(B[E][i][1]!=fa)Si[E][q]+=dffffff(E,B[E][i][1],q);
return Si[E][q];
}
Uin er1[N],er2[N];
Uin H1,H2;
void dfsf(int E,int q,int fa,int c)
{
Uin cl=bv[E][q]-(fa!=0);
cl=Si[E][q]*Si[E][q]*Si[E][q]*23333LL;
p[E][q].i=q;p[E][q].k=E;
p[E][q].sh1=p[E][q].h1=er1[c]*(Si[E][q]*Si[E][q]%h1mo*Si[E][q]*23333LL%h1mo-bv[E][q]*bv[E][q]%h1mo)%h1mo;
p[E][q].sh2=p[E][q].h2=er2[c]*(Si[E][q]*Si[E][q]%h2mo*Si[E][q]*23333LL%h2mo-bv[E][q]*bv[E][q]%h2mo)%h2mo;
efo(i,q)if(B[E][i][1]!=fa)
{
dfsf(E,B[E][i][1],q,c+1);
p[E][q].sh1+=p[E][B[E][i][1]].sh1;
p[E][q].sh2+=p[E][B[E][i][1]].sh2;
if(p[E][q].sh2>=h2mo)p[E][q].sh2-=h2mo;
if(p[E][q].sh1>=h1mo)p[E][q].sh1-=h1mo;
}
}
void dfs(int E,int q,int fa,Uin h1,Uin h2)
{
h2=(h2%h2mo+h2mo)%h2mo;
h1=(h1%h1mo+h1mo)%h1mo;
p[E][q].z1=((LL)p[E][q].h1+(LL)41LL*p[E][q].sh1%h1mo+(LL)h1*443ll%h1mo+111LL*p[E][fa].z1)%h1mo;
p[E][q].z2=((LL)p[E][q].h2+(LL)87*p[E][q].sh2%h2mo+(LL)h2*47%h2mo+(LL)13143LL*p[E][fa].z2)%h2mo;
H1=(H1+p[E][q].z1)%h1mo;
H2=(H2+p[E][q].z2)%h2mo;
h1=(h1+p[E][q].sh1)%h1mo;
h2=(h2+p[E][q].sh2)%h2mo;
efo(i,q)if(B[E][i][1]!=fa)
dfs(E,B[E][i][1],q,h1-p[E][B[E][i][1]].sh1,h2-p[E][B[E][i][1]].sh2);
}
bool OK;
bool PX(qqww q,qqww w){return q.z1q.z1==w.z1&&q.z2int q,int w,int fa)
{
if(!OK)return;
if(p[0][q].z1!=p[1][w].z1||p[0][q].z2!=p[1][w].z2){OK=0;return;}
Ans[q]=w;
int E=0;
int t1=0;
efo(i,q)p1[++t1]=p[0][B[0][i][1]];
sort(p1+1,p1+1+t1,PX);
E=1;
int t2=0;
efo(i,w)p2[++t2]=p[1][B[1][i][1]];
sort(p2+1,p2+1+t2,PX);
if(t1!=t2){OK=0;return;}
fod(i,t1,1)link(2,q,p1[i].i);
fod(i,t1,1)link(3,w,p2[i].i);
for(int i=A[2][q],j=A[3][w];i;i=B[2][i][0],j=B[3][j][0])if(!Ans[B[2][i][1]])dfsS(B[2][i][1],B[3][j][1],q);
}
int main()
{
freopen("check.in","r",stdin);
freopen("check.out","w",stdout);
int q,w;
read(n);
er1[1]=23;fo(i,2,n)er1[i]=(er1[i-1]*23LL)%h1mo;
er2[1]=67;fo(i,2,n)er2[i]=(er2[i-1]*67LL)%h2mo;
fo(i,1,n-1)read(q),read(w),link(0,q,w);
fo(i,1,n-1)read(q),read(w),link(1,q,w);
Sz=1e9;
FDz(0,1,0);
Sz=1e9;
FDz(1,1,0);
OK=0;
fo(I,1,d[0][0])fo(J,1,d[1][0])if(bv[0][d[0][I]]==bv[1][d[1][J]])
{
q=d[0][I];w=d[1][J];
dffffff(0,q,0);dffffff(1,w,0);
dfsf(0,q,0,1);
H1=H2=0;dfs(0,q,0,0,0);
Uin q1=H1,q2=H2;
dfsf(1,w,0,1);
H1=H2=0;dfs(1,w,0,0,0);
if(q1!=H1||q2!=H2)continue;
OK=1;
dfsS(q,w,0);
if(OK)break;
}
if(!OK){printf("NO\n");return 0;}
printf("YES\n");
fo(i,1,n)printf("%d ",Ans[i]);
return 0;
}