theory

http://192.168.102.138/JudgeOnline/problem.php?cid=1274&pid=2

知识点:1.最大权闭合子图

    2.定义关键点:如果x在闭合图内,则由x通向的任何一个点也一定要在闭合图内,即不存在任何一个闭合子图内的点的出度不在闭合子图内

    3.网络流

    4.做法:正数向S建边,负数向T建边,其它边保留

    5.正数连S的边流为原数,负数连T的边流为原数的相反数,其它边的流量为inf

    6.最后的答案就是(正数和) - (最小割)

#include <bits/stdc++.h>
using namespace std;
const int S = 520,T = 521;
int T1,n;
struct edge
{
    int to;
    int nxt;
}t1[1010],t2[1010];
int ct1,ct2 ;
int head1[1010],head2[1010];
void add(int x,int y)
{
    t1[++ct1].nxt = head1[x];
    t1[ct1].to = y;
    head1[x] = ct1;
}
void add1(int x,int y)
{
    t2[++ct2].nxt = head2[x];
    t2[ct2].to = y;
    head2[x] = ct2;
}
struct flow
{
    int to;
    int nxt;
    int len;
}e[1010];
int bg[1010],cnt1 = 1;
void add2(int x,int y,int len)
{
    e[++cnt1].nxt = bg[x];
    e[cnt1].to = y;
    e[cnt1].len = len;
    bg[x] = cnt1;
}
int f[1010];
int psum = 0;
int rt = 0;
int ans = -1;
int fa[1010];
int deep[1100];
queue <int> q;
int bfs()
{
    memset(deep,0,sizeof(deep));
    deep[S] = 1;
    q.push(S);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int i = bg[u];i;i  = e[i].nxt)
        {
            int np = e[i].to;
            if(deep[np] == 0 && e[i].len)
            {
                deep[np] = deep[u] + 1;
                q.push(np);
            }
        }
    }

    if(deep[T] == 0)return 0;
    else return 1;
}
int dfs(int t,int minn)
{
    if(t == T)
    return minn;
    int tans = 0;
    for(int i = bg[t];i;i = e[i].nxt)
    {
        if(e[i].len)
        {
            int np = e[i].to;
            if(deep[np] == deep[t] + 1)
            {
                int he1 = dfs(np,min(e[i].len,minn));
                if(he1)
                {
                    tans += he1;
                    minn -= he1;
                    e[i].len -= he1;
                    e[i^1].len += he1;
                    if(minn == 0)break;
                }
            }
        }
    }
    return tans;
}
void dfs1(int now,int fat)
{
    if(fat != 0)add2(now,fat,999999999),add2(fat,now,0);
    for(int i = head1[now];i ;i = t1[i].nxt)
    {
        int to = t1[i].to;
        if(to != fat)dfs1(to,now);    
    }
} 
void dfs2(int now,int fat)
{
    if(fat  != 0)add2(now,fat,999999999),add2(fat,now,0);
    for(int i = head2[now];i ;i = t2[i].nxt)
    {
        int to = t2[i].to;
        if(to != fat)dfs2(to,now);    
    }
}
int calc(int t)
{
    cnt1 = 1;
    memset(bg,0,sizeof(bg));
    dfs1(t,0);
    dfs2(t,0);
    for(int i = 1;i <= n;i++)
    {
        if(f[i] > 0)add2(S,i,f[i]),add2(i,S,0);
        else if(f[i] < 0) add2(i,T,-f[i]),add2(T,i,0);
    }
    int lsp = 0;
    int SUM = 0;
    while(bfs())
    {
        SUM += dfs(S,999999999);
    }
    return psum - SUM;    
}
int main()
{
    scanf("%d",&T1);
    while(T1--)
    {
        scanf("%d",&n);
        for(int i = 1;i <= n;i++)scanf("%d",&f[i]);
        int x,y;
        for(int i = 1;i <= n - 1;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        for(int i = 1;i <= n - 1;i++)
        {
            scanf("%d%d",&x,&y);
            add1(x,y),add1(y,x);
        }
        for(int i = 1;i <= n;i++)if(f[i] > 0)psum += f[i];
        ans = 0;
        for(int i = 1;i <= n;i++)if(f[i] > 0)ans = max(ans,calc(i));
        printf("%d\n",ans);
        psum = 0;
        rt = 0;
        ans = 0;
        ct1 = ct2 = 0;
        memset(head1,0,sizeof(head1));
        memset(head2,0,sizeof(head2));
    }    
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int M  = 107;
const int INF = 1e9+7;
int rd()
{
    int xx;
    cin >> xx;
    return xx;
} 
int tcas,n,ans;
int a[M];
struct edge
{
    int y,nxt,f;
    edge(int _y=0,int _nxt=0,int _f=0){y=_y;nxt=_nxt;f=_f;}
};
struct vec
{
    int g[M],te;
    edge e[M * 6];
    vec(){te = 1;memset(g,0,sizeof(g));}
    void clear(){te = 1;memset(g,0,sizeof(g));}
    inline void push(int x,int y,int f=0)
    {
        e[++te] = edge(y,g[x],f); 
        g[x] = te;
        e[++te] = edge(x,g[y],0); 
        g[y] = te;
    }
    inline int& operator () (int x){return g[x];}
    inline edge& operator [] (int x){return e[x];}
}e[2],G;
int S,T;
int q[M];
int lev[M];
bool bfs()
{
    int h=0,t=1,x,p,y;
    memset(lev,0,sizeof(lev));
    q[1]=S; lev[S]=1;
    while(h^t)
    {
        x=q[++h];
        for(p=G(x);p;p=G[p].nxt)
        if(G[p].f>0&& !lev[y=G[p].y])
        {
            lev[y]=lev[x]+1;
            if(y==T) return 1;
            q[++t]=y;
        }
    }
    return 0;
}
int dinic(int x,int fl)
{
    if(x==T) return fl;
    int p,y,tp,res=0;
    for(p=G(x);p;p=G[p].nxt)
    if(G[p].f&&lev[x]+1==lev[y=G[p].y])
    {
        tp=dinic(y,min(fl,G[p].f));
        if(tp>0)
        {
            res+=tp;
            fl-=tp;
            G[p].f-=tp;
            G[p^1].f+=tp;
        }
        if(fl==0) return res;
    }
    if(res==0) lev[x]=0;
    return res;
}
void dfs(int z,int x,int fa)
{
    if(fa>0) G.push(x,fa,INF);
    int p,y;
    for(p=e[z](x);p;p=e[z][p].nxt)
    if((y=e[z][p].y)!=fa) dfs(z,y,x);
}
int solve(int x)
{
    int res=0;
    G.clear();
    dfs(0,x,0);
    dfs(1,x,0);
    for(int i = 1;i <= n;i++)
    {
        if(a[i] > 0) G.push(S,i,a[i]),res += a[i];
        else if(a[i] < 0) G.push(i,T,-a[i]);
    }
    while(bfs())
        res-=dinic(S,INF);
    return res;
}
int main()
{ 
    tcas=rd();
    while(tcas--)
    {
        n=rd();
        S=0, T=n+1;
        for(int i=1;i<=n;i++) a[i]=rd();
        e[0].clear(), e[1].clear();
        for(int i=1;i<n;i++) e[0].push(rd(),rd());
        for(int i=1;i<n;i++) e[1].push(rd(),rd());
        ans=0;
        for(int i=1;i<=n;i++) ans=max(ans,solve(i));
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2020-09-16 12:50  ywwywwyww  阅读(273)  评论(0编辑  收藏  举报