51nod1325 两棵树的问题

来源:互联网 发布:乐高淘宝店 编辑:程序博客网 时间:2024/05/22 08:20

枚举一个必选的点,把它作为根,那么其它点依赖且只依赖于它的父亲。用最大权闭合子图求解。

#include<cstdio>#include<vector>#include<algorithm>using namespace std;const int maxn=100000,oo=0x3f3f3f3f;int fir[maxn],ne[maxn],to[maxn],w[maxn],val[maxn],dep[maxn],que[maxn],n,s,t,num;vector<int> tree[2][maxn];void check(){    for (int i=0;i<=t;i++)        for (int j=fir[i];j;j=ne[j])            if (w[j]) printf("%d->%d:%d\n",i,to[j],w[j]);}void add(int u,int v,int x){    num++;    ne[num*2]=fir[u];    fir[u]=num*2;    to[num*2]=v;    w[num*2]=x;    ne[num*2+1]=fir[v];    fir[v]=num*2+1;    to[num*2+1]=u;    w[num*2+1]=0;}void dfs0(int f,int u,int fa){    for (int v:tree[f][u])        if (v!=fa)        {            add(v,u,oo);            dfs0(f,v,u);        }}int bfs(){    int hd=1,tl=1,u,v;    for (int i=0;i<=t;i++) dep[i]=0;    dep[que[1]=s]=1;    while (hd<=tl)    {        u=que[hd++];        for (int i=fir[u];i;i=ne[i])            if (w[i]&&!dep[v=to[i]])            {                dep[v]=dep[u]+1;                que[++tl]=v;            }    }    return dep[t];}int dfs(int u,int lim){    int x,ret=0,v;    if (u==t) return lim;    for (int i=fir[u];i&&ret<lim;i=ne[i])        if (w[i]&&dep[v=to[i]]==dep[u]+1)        {            x=dfs(v,min(lim-ret,w[i]));            w[i]-=x;            w[i^1]+=x;            ret+=x;        }    if (ret<lim) dep[u]=0;    return ret;}int main(){    int ans=0,res,x,y;    scanf("%d",&n);    for (int i=0;i<n;i++) scanf("%d",&val[i]);    for (int i=1;i<n;i++)    {        scanf("%d%d",&x,&y);        tree[0][x].push_back(y);        tree[0][y].push_back(x);    }    for (int i=1;i<n;i++)    {        scanf("%d%d",&x,&y);        tree[1][x].push_back(y);        tree[1][y].push_back(x);    }    s=n,t=n+1;    for (int i=0;i<n;i++)    {        for (int j=0;j<=n+1;j++) fir[j]=0;        num=0;        res=val[i];        for (int j=0;j<n;j++)            if (j!=i)            {                if (val[j]>0)                {                    res+=val[j];                    add(s,j,val[j]);                }                else add(j,t,-val[j]);            }        for (int v:tree[0][i]) dfs0(0,v,i);        for (int v:tree[1][i]) dfs0(1,v,i);        //check();        while (bfs()) res-=dfs(s,oo);        ans=max(ans,res);    }    printf("%d\n",ans);}
原创粉丝点击