51nod1325 两棵树的问题

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

#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);
}

猜你喜欢

转载自blog.csdn.net/sdfzyhx/article/details/74841861