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