最大权闭包模型中源点与正收益的点连边,负收益的点与汇点连边,容量取绝对值,然后相关联的点之间之间连容量为无穷大的边。
具体可参见胡伯涛:《最小割模型在信息学竞赛中的应用》
HDU 3061 Battle
应该是最裸的最大权闭包题了。
1 #include <vector> 2 #include <list> 3 #include <map> 4 #include <set> 5 #include <queue> 6 #include <deque> 7 #include <stack> 8 #include <algorithm> 9 #include <sstream> 10 #include <iostream> 11 #include <iomanip> 12 #include <cstdio> 13 #include <cstdlib> 14 #include <cstring> 15 #include <cmath> 16 #include <queue> 17 using namespace std; 18 #define pii pair<LL,LL> 19 #define clr(a) memset((a),0,sizeof (a)) 20 #define rep(i,a,b) for(LL i=(a);i<=(LL)(b);i++) 21 #define per(i,a,b) for(LL i=(a);i>=(LL)(b);i--) 22 #define oo ((LL)2000000007)*((LL)2000000007) 23 #define eps 1e-6 24 #define MAXN 1005 25 #define MAXM 200005 26 #define MOD 1000000007 27 #define debug puts("reach here") 28 #define MP make_pair 29 #define PB push_back 30 #define RI(x) scanf("%I64d",&x) 31 #define RII(x,y) scanf("%I64d%I64d",&x,&y) 32 #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z) 33 typedef long long LL; 34 35 struct Edge 36 { 37 int u, v, next; 38 LL w; 39 }E[MAXM]; 40 41 int gap[MAXN], pre[MAXN], cur[MAXN], dis[MAXN]; 42 LL n, m; 43 LL N; 44 int head[MAXN], NE; 45 bool vis[MAXN]; 46 47 void add_edge (int u, int v, LL w) 48 { 49 E[NE].u = u; E[NE].v = v; E[NE].w = w; E[NE].next = head[u]; head[u] = NE++; 50 E[NE].u = v; E[NE].v = u; E[NE].w = 0; E[NE].next = head[v]; head[v] = NE++; 51 } 52 53 inline void checkmin(LL &a,LL b) {if(a == -1 || a > b)a = b;} 54 55 LL sap(int s, int t) 56 { 57 clr(dis); clr(gap); 58 for(int i=0;i<N;++i) cur[i]=head[i]; 59 int u=pre[s]=s; 60 LL maxflow=0; 61 LL aug=-1; 62 gap[0]=N; 63 while(dis[s]<N) 64 { 65 loop:for(int &i=cur[u];i!=-1;i=E[i].next) 66 { 67 LL v=E[i].v; 68 if(E[i].w && dis[u]==dis[v]+1) 69 { 70 checkmin(aug,E[i].w); 71 pre[v]=u; 72 u=v; 73 if(v==t) 74 { 75 maxflow += aug; 76 for(u=pre[u];v!=s;v=u,u=pre[u]) 77 { 78 E[cur[u]].w-=aug; 79 E[cur[u]^1].w+=aug; 80 } 81 aug=-1; 82 } 83 goto loop; 84 } 85 } 86 int mindis=N; 87 for(int i=head[u];i!=-1;i=E[i].next) 88 { 89 int v=E[i].v; 90 if(E[i].w && mindis>dis[v]) 91 { 92 cur[u]=i; 93 mindis=dis[v]; 94 } 95 } 96 if((--gap[dis[u]])==0) break; 97 gap[dis[u]=mindis+1]++; 98 u=pre[u]; 99 } 100 return maxflow; 101 } 102 103 void init() 104 { 105 NE = 0; 106 memset(head, -1, sizeof head); 107 } 108 109 int main() 110 { 111 int a, b; 112 LL sum, v; 113 while(RII(n, m) != EOF) 114 { 115 init(); 116 LL s = 0, t = n + 1; 117 sum = 0; 118 N = t + 1; 119 rep(i,1,n) 120 { 121 RI(v); 122 if(v > 0) 123 { 124 add_edge(s, i, v); 125 sum += v; 126 } 127 else 128 add_edge(i, t, -v); 129 } 130 rep(i,1,m) 131 { 132 scanf("%d%d", &a, &b); 133 add_edge(a, b, oo); 134 } 135 printf("%I64d\n", sum - sap(s, t)); 136 } 137 return 0; 138 }