您的位置:首页 > 其它

【SDOI2013】【BZOJ3197】assassin

2016-02-17 14:57 387 查看
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];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树同构 Hash DP 费用流