Description
JYY有两棵树A和B:树A有N个点,编号为1到N;树B有N+1个点,编号为1到N+1。JYY知道树B恰好是由树A加上一个叶
节点,然后将节点的编号打乱后得到的。他想知道,这个多余的叶子到底是树B中的哪一个叶节点呢?
Input
输入一行包含一个正整数N。
接下来N-1行,描述树A,每行包含两个整数表示树A中的一条边;
接下来N行,描述树B,每行包含两个整数表示树B中的一条边。
1≤N≤10^5
Output
输出一行一个整数,表示树B中相比树A多余的那个叶子的编号。如果有多个符合要求的叶子,输出B中编号最小的
那一个的编号
树形dp求出两棵树每个点的子树和上方子树的hash值,进而可以求出每个点作为根的整棵树(或删去一个叶子后)的hash值
有根树的hash的一个实现方式是递归定义为Hash(子树的hash值排序后的字符串hash)
#include<cstdio> #include<cstdlib> #include<algorithm> #define G *++ptr typedef long long i64; const int N=100007,p1=1844677,p2=2939999,p=1234577; char buf[N*40],*ptr=buf-1; int _(){ int x=0,c=G; while(c<48)c=G; while(c>47)x=x*10+c-48,c=G; return x; } int n,ans=0x3f3f3f3f; struct H{ int a,b; H&cal(){ a=(a*2+b%5112+135411)%p1; b=(b+a%1237+212411)%p2; return*this; } }; H operator*(H x,i64 y){return (H){x.a*y%p1,x.b*y%p2};} H operator*(H x,H y){return (H){i64(x.a)*y.a%p1,i64(x.b)*y.b%p2};} H operator+(H x,H y){return (H){(x.a+y.a)%p1,(x.b+y.b)%p2};} H operator-(H x,H y){return (H){(x.a-y.a+p1)%p1,(x.b-y.b+p2)%p2};} bool operator<(H x,H y){return x.a!=y.a?x.a<y.a:x.b<y.b;} int cp=0,vp=0; H*cs[N],pp[N],hs[N],vs[N]; bool cmp(H*a,H*b){return *a<*b;} bool is(H x){return std::binary_search(vs,vs+vp,x);} struct tree{ int es[N*2],enx[N*2],e0[N],ep,n; H f1[N],f2[N]; void init(int _n){ ep=2; n=_n; for(int i=1,a,b;i<n;++i){ a=_();b=_(); es[ep]=b;enx[ep]=e0[a];e0[a]=ep++; es[ep]=a;enx[ep]=e0[b];e0[b]=ep++; } dfs1(1,0); dfs2(1,0); } void dfs1(int w,int pa){ for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa)dfs1(u,w); } cp=0; for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa)cs[cp++]=f1+u; } std::sort(cs,cs+cp,cmp); for(int i=0;i<cp;++i)f1[w]=f1[w]*p+*cs[i]; f1[w].cal(); } void getcs(int w,int pa){ cp=0; for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa)cs[++cp]=f1+u; else cs[++cp]=f2+w; } std::sort(cs+1,cs+cp+1,cmp); } void dfs2(int w,int pa){ getcs(w,pa); for(int i=1;i<=cp;++i)hs[i]=hs[i-1]*p+*cs[i]; for(int i=1;i<=cp;++i){ if(cs[i]==f2+w)continue; f2[cs[i]-f1]=(hs[cp]+(hs[i-1]-hs[i])*pp[cp-i]).cal(); } for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa)dfs2(u,w); } } void dfs3(int w,int pa){ getcs(w,pa); for(int i=1;i<=cp;++i)hs[i]=hs[i-1]*p+*cs[i]; for(int i=1;i<=cp;++i){ if(cs[i]==f2+w)continue; int u=cs[i]-f1; if(!enx[e0[u]]&&u<ans&&is((hs[cp]+(hs[i-1]-hs[i])*pp[cp-i]).cal()))ans=u; } for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa)dfs3(u,w); } } void spj(){ if(!enx[e0[1]]&&is(f1[es[e0[1]]]))puts("1"),exit(0); } void dfs4(int w,int pa){ getcs(w,pa); for(int i=1;i<=cp;++i)vs[vp]=vs[vp]*p+*cs[i]; vs[vp++].cal(); for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa)dfs4(u,w); } } }A,B; int main(){ fread(buf,1,sizeof(buf),stdin)[buf]=0; n=_(); pp[0]=(H){1,1}; for(int i=1;i<=n;++i)pp[i]=pp[i-1]*p; A.init(n); B.init(n+1); A.dfs4(1,0); std::sort(vs,vs+vp); B.spj(); B.dfs3(1,0); printf("%d",ans); return 0; }