analysis
After understand the meaning of the questions will be thinking more clearly , although I do not know about, please dalao their emotional understanding
For dynamic root topic, we can consider two trees with the use of a root, then isomorphic tree has magical properties: If the center of gravity to force the two trees is the root, then the two trees isomorphic if and only if this two rooted tree isomorphic
But the center of gravity may have two of it, we just need to disconnect between the two sides of the center of gravity, and then create a point connecting the two center of gravity, a new point is the new center of gravity
We can think of the tree with the depth of homogeneous parts can be exchanged in order to reduce costs
Isomorphic? Hash trees slightly
After processing the hash value of each point, we let F [u] [v] is the root of u to v and subtree rooted subtree isomorphism, and the completion of the initial state u to v sub subtree the minimum cost of the final state of the tree
Obviously, this shift from their son up at
Then we can see, the process is selecting a number of transfer points in which two sub-tree, the cost of selecting a pair of f [su] [sv], minimize the total cost of
This is a weighted bipartite graph algorithms available KM or cost flow algorithm to solve
Recommended KM, cost flow algorithm needs to pay attention to space, code complexity
#include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> #include <queue> using namespace std; const int N=7e2+10; const int P=76447; struct Graph { int u,v,nx; }g[2*N]; struct Cube { int u,v,nx,c,w; }t[2*N*N+4*N]; int cnt,list[N],vis[2*N],dep[N],flow[2*N],dis[2*N],fa[2*N]; int g1,g2,sz[N],mxsize; int h[N],xx[N],f[N][N],p[N]; int n,from[N],to[N],ans; void Add(int u,int v) { g[++cnt]=(Graph){u,v,list[u]};list[u]=cnt; g [ ++ cnt] = (Graph) {v, u, list [v]}; list [v] = cnt; } void Add_Cube ( you and, you v, you w, you c) { t[++cnt]=(Cube){u,v,flow[u],c,w};flow[u]=cnt; t[++cnt]=(Cube){v,u,flow[v],0,-w};flow[v]=cnt; } void Find_G(int u,int f) { int size=0; sz[u]=1; for (int i=list[u];i;i=g[i].nx) if (g[i].v!=f) { Find_G (g [i] .v, u); c [u] + = c [g [i] .V]; size=max(size,sz[g[i].v]); } size=max(size,n-sz[u]); if (size==mxsize) g2=u; if (size<mxsize) { mxsize=size; g1=u; g2=0; } } void Tree_Hash(int u,int f) { int xcnt=0;dep[u]=dep[f]+1; for (int i=list[u];i;i=g[i].nx) if (g[i].v!=f) Tree_Hash(g[i].v,u); for (int i=list[u];i;i=g[i].nx) if (g[i].v!=f) xx[++xcnt]=h[g[i].v]; sort(xx+1,xx+xcnt+1); h[u]=17731; for (int i=1;i<=xcnt;i++) h[u]=(h[u]*7441%P+xx[i])%P; h[u]=h[u]*3119%P; } bool CMP(int u,int v) { return dep[u]!=dep[v]?dep[u]>dep[v]:h[u]<h[v]; } bool SPFA() { queue<int> q; while (!q.empty()) q.pop(); memset(dis,0x3f,sizeof dis); dis[0]=0;q.push(0); while (!q.empty()) { int u=q.front();q.pop(); for (int i=flow[u];i;i=t[i].nx) if (dis[t[i].v]>dis[u]+t[i].w&&t[i].c) { dis[t[i].v]=dis[u]+t[i].w; fa[t[i].v]=i; if (!vis[t[i].v]) q.push(t[i].v); force [t [i] x] = 1 ; } Height [i] = 0 ; } return dis[2*n+1]!=0x3f3f3f3f; } void Get_Ans() { int x=2*n+1,mf=2147483647; while (fa[x]) { years + = t [f [x]] w. D = min (D, t [four [x]]. c); x=t[fa[x]].u; } x=2*n+1; while (fa[x]) { t[fa[x]].c-=mf; t[fa[x]^1].c+=mf; x=t[fa[x]].u; } } int Min_Cost_Flow() { years = 0 ; while (PFAS ()) Get_Ans (); return years; } void DP() { for (int i=1;i<=n;i++) p[i]=i; sort(p+1,p+n+1,CMP); for (int i=1;i<=n;) { int j=i; for (;j<=n;j++) if (dep[p[i]]!=dep[p[j]]||h[p[i]]!=h[p[j]]) break; for (int k=i;k<j;k++) for (int l=i;l<j;l++) { int u=p[k],v=p[l]; cnt=1;memset(flow,0,sizeof flow); for (int sv=list[v];sv;sv=g[sv].nx) if (dep[g[sv].v]==dep[v]+1) Add_Cube (n + g [St] .v, 2 * n + 1 , 0 , 1 ); for ( int are = list [i]; the; as = g [the] .nx) and f (dep [g [the] .v] dep == [i] + 1 ) { Add_Cube ( 0 , g [su] .v, 0 , 1 ); for ( int sv = list [v]; sv; sv = g [sv] .nx) if (dep [g [sv] .v] == dep [v] + 1 && h [g [su] .v ] = = h [g [sv] .v]) Add_Cube (g [su] .v, n + g [sv] .v, f [g [su] .v] [g [sv] .v], 1 ); } f[u][v]=Min_Cost_Flow()+(from[u]!=to[v]); } i=j; } } int main () { scanf("%d",&n); for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v); for (int i=1;i<=n;i++) scanf("%d",&from[i]); for (int i=1;i<=n;i++) scanf("%d",&to[i]); mxsize=n; Find_G(1,0); if (g2) { cnt=0;memset(list,0,sizeof list); for (int i=1,j=1;i<=n-1;i++,j=i*2-1) if ((g[j].u!=g1||g[j].v!=g2)&&(g[j].v!=g1||g[j].u!=g2)) Add(g[j].u,g[j].v); Add(g1,n+1),Add(n+1,g2); n++; g1=n; } Tree_Hash(g1,0); DP(); printf("%d",f[g1][g1]); }