【ZJOJ 5454】【NOIP2017提高A组冲刺11.5】仔细的检查

来源:互联网 发布:福建广播网络电视台 编辑:程序博客网 时间:2024/05/29 19:20

Description

nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上。另一天nodgd更无聊,就又画了一张。
这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到n进行了编号,即每棵树有n个节点。
如果存在一个1到n的排列p1p2…pn,对于第一幅图中的任意一条边(u,v),在第二幅图中都能找到一条边(pu,pv),则认为这两幅图中的树是一样的。

Solution

树的哈希版子题,
(写得越猎奇越好)

Code

#include <cstdio>#include <algorithm>#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 67const Uin h1mo=4988741;//23 67int 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(mx<Sz)    {        Sz=mx;        d[E][d[E][0]=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.z1<w.z1||(q.z1==w.z1&&q.z2<w.z2);}void dfsS(int 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;}