Description
Input
Output
Sample Input
4
1 2
2 3
3 4
0 0 1 1
1 0 0 0
Sample Output
1
HINT
暑假时候高大哥出来考试的题
丢题解跑
gty大哥的题解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 710
#define GET (ch>='0'&&ch<='9')
#define ULL unsigned long long
#define base 43
using namespace std;
int n,top,root;
int S=0,T=29;
int a[MAXN],b[MAXN];
int fa[MAXN],size[MAXN],deep[MAXN],g[2];
int f[MAXN][MAXN];
ULL hash[MAXN];
struct edge
{
int to;
edge *next,*rev;
}e[MAXN<<1],*prev[MAXN];
struct node
{
int deep,id;
ULL hash;
bool operator <(const node& a)const { return deep==a.deep?hash<a.hash:deep>a.deep; }
bool operator ==(const node& a)const { return deep==a.deep&&hash==a.hash; }
}s[MAXN];
void insert(int u,int v) { e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top]; }
void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
void dfs1(int x,int f)//Find G
{
size[x]=1;fa[x]=f;bool flag=1;
for (edge *i=prev[x];i;i=i->next)
if (i->to!=f)
{
dfs1(i->to,x);size[x]+=size[i->to];
if (size[i->to]>n>>1) flag=0;
}
if (n-size[x]>n>>1) flag=0;
if (flag)
for (int i=0;i<=1;i++) if (!g[i]) { g[i]=x;break; }
}
void dfs2(int x,int f)//Get Hash
{
deep[x]=deep[f]+1;int Top=0;ULL sta[MAXN];fa[x]=f;
for (edge *i=prev[x];i;i=i->next) if (i->to!=f) dfs2(i->to,x);
for (edge *i=prev[x];i;i=i->next) if (i->to!=f) sta[++Top]=hash[i->to];
sort(sta+1,sta+Top+1);hash[x]=41;
for (int i=1;i<=Top;i++) (((hash[x]*=base)^=sta[i])+=sta[i])^=sta[i];
}
int tp,ret;
struct Edge
{
int from,to,c,w;
Edge *next,*rev;
}E[10010],*Prev[32],*from[32];
void Insert(int u,int v,int f,int w) { E[++tp].to=v;E[tp].from=u;E[tp].next=Prev[u];Prev[u]=&E[tp];E[tp].c=f;E[tp].w=w; }
void add(int u,int v,int f,int w) { Insert(u,v,f,w);Insert(v,u,0,-w);E[tp].rev=&E[tp-1];E[tp-1].rev=&E[tp]; }
bool cmp(int a,int b) { return hash[a]<hash[b]; }
int spfa()
{
bool vis[32];memset(vis,0,sizeof(vis));
int dis[32];memset(dis,0x3f,sizeof(dis));
vis[S]=1;dis[S]=0;queue<int> q;q.push(S);
while (!q.empty())
{
int x=q.front();q.pop();vis[x]=0;
for (Edge *i=Prev[x];i;i=i->next)
if (i->c>0&&dis[i->to]>dis[x]+i->w)
{
dis[i->to]=dis[x]+i->w;from[i->to]=i;
if (!vis[i->to]) vis[i->to]=1,q.push(i->to);
}
}
return dis[T]!=0x3f3f3f3f;
}
void dfs()
{
int minn=0x3f3f3f3f;
for (Edge *i=from[T];i;i=from[i->from]) minn=min(minn,i->c);
for (Edge *i=from[T];i;i=from[i->from]) ret+=minn*i->w,i->c-=minn,i->rev->c+=minn;
}
int calc(int x,int y)
{
int sta1[MAXN],sta2[MAXN],tp1=0,tp2=0,i=0,j=0;
for (edge *i=prev[x];i;i=i->next) if (i->to!=fa[x]) sta1[++tp1]=i->to;
for (edge *i=prev[y];i;i=i->next) if (i->to!=fa[y]) sta2[++tp2]=i->to;
sort(sta1+1,sta1+tp1+1,cmp);sort(sta2+1,sta2+tp2+1,cmp);
memset(Prev,0,sizeof(Prev));memset(E,0,sizeof(Edge)*(tp+3));tp=0;ret=0;
for (i=1;i<=tp1;i=j)
{
for (j=i+1;j<=tp1&&hash[sta1[i]]==hash[sta1[j]];j++);
for (int k=i;k<j;k++) for (int l=i;l<j;l++) add(k,tp1+l,1,f[sta1[k]][sta2[l]]);
}
for (int i=1;i<=tp1;i++) add(S,i,1,0),add(i+tp1,T,1,0);
while (spfa()) dfs();
return ret+(a[x]^b[y]);
}
int main()
{
in(n);int u,v,r=0;
for (int i=1;i<n;i++) in(u),in(v),insert(u,v),insert(v,u),e[top].rev=&e[top-1],e[top-1].rev=&e[top];
for (int i=1;i<=n;i++) in(a[i]);
for (int i=1;i<=n;i++) in(b[i]);
dfs1(1,0);
if (g[1])
{
root=++n;
for (edge *i=prev[g[0]];i;i=i->next) if (i->to==g[1]) { i->to=i->rev->to=n;break; }
insert(n,g[0]);insert(n,g[1]);
}
else root=g[0];
dfs2(root,0);
for (int i=1;i<=n;i++) s[i]=(node){deep[i],i,hash[i]};
sort(s+1,s+n+1);
for (int l=1;l<=n;l=r)
{
for (r=l+1;r<=n&&s[l]==s[r];r++);
for (int x=l;x<r;x++) for (int y=l;y<r;y++)
f[s[x].id][s[y].id]=calc(s[x].id,s[y].id);
}
cout<<f[root][root];
}