网络流五·最大权闭合子图 HihoCoder - 1398
网络流五·最大权闭合子图
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxv = 410; 4 const int maxe = 40210; 5 const int inf = 0x3f3f3f3f; 6 struct Edge{ 7 int u, v, nex; 8 int cap, flow; 9 Edge(int u=0, int v=0, int nex=0, int cap=0, int flow=0): 10 u(u), v(v), nex(nex), cap(cap), flow(flow){} 11 }e[maxe<<1]; 12 int head[maxv]; 13 int cnt; 14 void init(){ 15 memset(head, -1, sizeof(head)); 16 cnt = 0; 17 } 18 19 void add(int u, int v, int cap){ 20 e[cnt] = Edge(u, v, head[u], cap, 0); 21 head[u] = cnt++; 22 e[cnt] = Edge(v, u, head[v], 0, 0); 23 head[v] = cnt++; 24 } 25 26 int d[maxv], num[maxv], cur[maxv], p[maxv]; 27 int vis[maxv]; 28 int S, T; 29 int N; 30 31 void bfs(){ 32 memset(d, -1, sizeof(d)); 33 memset(vis, 0, sizeof(vis)); 34 queue<int> q; 35 q.push(T); 36 d[T] = 0; 37 vis[T] = 1; 38 while(!q.empty()){ 39 int u = q.front(); 40 q.pop(); 41 for(int i = head[u]; ~i; i = e[i].nex){ 42 int id = i&(-2); //正边 43 int v = e[id].u; 44 if(!vis[v] && e[id].cap > e[id].flow){ 45 vis[v] = 1; 46 d[v] = d[u] + 1; 47 q.push(v); 48 } 49 } 50 } 51 } 52 53 int augment(){ 54 int u = T; 55 int a = inf; 56 while(u!=S){ 57 int id = p[u]; 58 a = min(a, e[id].cap - e[id].flow); 59 u = e[id].u; 60 } 61 u = T; 62 while(u!=S){ 63 int id = p[u]; 64 e[id].flow += a; 65 e[id^1].flow -= a; 66 u = e[id].u; 67 } 68 return a; 69 } 70 71 int ISAP(){ 72 bfs(); 73 int flow = 0; 74 memset(num, 0, sizeof(num)); 75 for(int i = 0; i < N; i++){ 76 cur [i] = head[i]; 77 if(~d[i]) num[d[i]]++; 78 } 79 int u = S; 80 while(d[S] < N){ 81 if(u == T){ 82 flow += augment(); 83 u = S; 84 } 85 int ok = 0; 86 for(int i = cur[u]; ~i; i = e[i].nex){ 87 int v = e[i].v; 88 if(d[u] == d[v]+1 && e[i].cap > e[i].flow){ 89 p[v] = i; 90 ok = 1; 91 cur[u] = i; 92 u = v; 93 break; 94 } 95 } 96 if(!ok){ 97 int m = N-1; 98 for(int i = head[u]; ~i; i = e[i].nex){ 99 if(e[i].cap > e[i].flow && ~d[e[i].v]) m = min(m, d[e[i].v]); 100 } 101 if(--num[d[u]] == 0) break; 102 num[d[u]=m+1]++; 103 cur[u] = head[u]; 104 if(u != S) u = e[p[u]].u; 105 } 106 } 107 return flow; 108 } 109 int main(){ 110 int n, m; 111 init(); 112 scanf("%d %d", &n, &m); 113 S = 0; 114 T = n+m+1; 115 N = T+1; 116 int res = 0; 117 int b; 118 for(int i = 1; i <= m; i++){ 119 scanf("%d", &b); 120 add(n+i, T, b); 121 } 122 for(int i = 1; i <= n; i++){ 123 int a, k, x; 124 scanf("%d %d", &a, &k); 125 add(S, i, a); 126 res += a; 127 for(int j = 0; j < k; j++){ 128 scanf("%d", &x); 129 add(i, n+x, inf); 130 } 131 } 132 int ans = ISAP(); 133 //cout<<res<<" "<<ans<<endl; 134 printf("%d\n", res - ans); 135 }