1. 程式人生 > >【ZJOJ 5454】【NOIP2017提高A組衝刺11.5】仔細的檢查

【ZJOJ 5454】【NOIP2017提高A組衝刺11.5】仔細的檢查

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 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(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; }