[Hash] [cost flow] JZOJ 3296] [SDOI2013 Assassin's Creed

Description

The story takes place in 1486 in Italy, Ezio was originally just a Renaissance nobility, and later because of family members being killed by the Knights Templar, determined to become an assassin. Eventually, by virtue of his efforts and outstanding talent, has become an outstanding Master Assassin, he is not only a nimble martial arts master, specializes in a variety Feiyanzoubi assassination operation. Assassin Under his leadership, the civilian population is being exploited for justice, the rule of Italy sent packing original leader of the Knights Templar - Pope Alexander VI. In his lifetime, he has experienced numerous thrilling, exciting adventure and assassination.

Once upon a time, in order to find clues left behind and equipment Altair, Ezio explore in Florence in Assassin grave. The assassin has many grave chamber, and there is only one unique path between any two chamber. These have a secret room assassin mark, he can start or shut down the assassin mark. In order to open the store for clues and equipment storage room, Ezio must operate to uncover the assassin mark the ancient seal. To unlock the seal, he needs to start by changing the situation of some assassin marked, so that all assassins mark and seal Password "look the same." Here, "look the same"

is defined as: the presence of a "mark" and chamber "Password" one correspondence between the chamber, so that the connection between the chamber and the same as starting (explained in more detail prompt) . Fortunately, before the assassin Ezio came to the tomb, with the help of Da Vinci, Ezio had been informed of the password needed to open the storage room.

And your task is to help achieve their goals Ezio to find the minimum number of marks required changes.
 

Input



The first line gives an integer n, denotes the number of chamber.

The second row to the n lines of two integers a and b are given, indicating the presence of an a-th channel between the chamber and a second chamber b.

The first row n + 1, n integers is given, respectively, when the start of each chamber in the case where (0 is off, 1 start).

N + 2 th row, n integers are given, respectively, to start the password of each chamber.

Output

Output only one line, i.e., the output minimalist tag number.
 

Sample Input

4
1 2
2 3
3 4
0 0 1 1
1 0 0 0

Sample Output

1
 

Data Constraint

For 30% of the data, n <= 10.

For 60% of the data, n <= 100.

To 100% of the data, n <= 700, and each chamber 11 communicates with the chamber up.
 

Hint

Sample explanation:

the Chamber of Secrets code can change! After the third chamber is closed, between the current mark and the password, there is a corresponding relation 1-> 4,2-> 3,3-> 2,4-> 1, renumbered connection is not changed, and the symbol corresponding password. For the more general case, there is a permutation P 1 to n, such that for any path between the uv chamber, both in the chamber must have a password road P (u) -P (v) ; if not present between the chamber road uv, be sure there is no password chamber of road P (u) -P (v) .

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]);
}
View Code

 

Guess you like

Origin www.cnblogs.com/mastervan/p/11104754.html