1. 程式人生 > >hihocoder1398 網路流五·最大權閉合子圖

hihocoder1398 網路流五·最大權閉合子圖

思路:

最大權閉合子圖。

實現:

  1 #include <bits/stdc++.h>
  2 
  3 #define N (405)
  4 #define M (N * N + 4 * N)
  5 const int INF = 0x3f3f3f3f;
  6 typedef long long LL;
  7 
  8 using namespace std;
  9 
 10 struct edge 
 11 {
 12     int v, cap, next;
 13 };
 14 edge e[M];
 15 
 16 int head[N], level[N], cur[N];
17 int num_of_edges; 18 19 void dinic_init(void) 20 { 21 num_of_edges = 0; 22 memset(head, -1, sizeof(head)); 23 return; 24 } 25 26 int add_edge(int u, int v, int c1, int c2) 27 { 28 int& i = num_of_edges; 29 30 assert(c1 >= 0 && c2 >= 0 && c1 + c2 >= 0
); // check for possibility of overflow 31 e[i].v = v; 32 e[i].cap = c1; 33 e[i].next = head[u]; 34 head[u] = i++; 35 36 e[i].v = u; 37 e[i].cap = c2; 38 e[i].next = head[v]; 39 head[v] = i++; 40 return i; 41 } 42 43 int dfs(int u, int t, int bn) 44 {
45 if (u == t) return bn; 46 int left = bn; 47 for (int &i = cur[u]; i >= 0; i = e[i].next) 48 { 49 int v = e[i].v; 50 int c = e[i].cap; 51 if (c > 0 && level[u] + 1 == level[v]) 52 { 53 int flow = dfs(v, t, min(left, c)); 54 if (flow > 0) 55 { 56 e[i].cap -= flow; 57 e[i ^ 1].cap += flow; 58 cur[u] = i; 59 left -= flow; 60 if (!left) break; 61 } 62 } 63 } 64 if (left > 0) level[u] = 0; 65 return bn - left; 66 } 67 68 bool bfs(int s, int t) 69 { 70 memset(level, 0, sizeof(level)); 71 level[s] = 1; 72 queue<int> q; 73 q.push(s); 74 while (!q.empty()) 75 { 76 int u = q.front(); 77 q.pop(); 78 if (u == t) return true; 79 for (int i = head[u]; i >= 0; i = e[i].next) 80 { 81 int v = e[i].v; 82 if (!level[v] && e[i].cap > 0) 83 { 84 level[v] = level[u] + 1; 85 q.push(v); 86 } 87 } 88 } 89 return false; 90 } 91 92 LL dinic(int s, int t) 93 { 94 LL max_flow = 0; 95 96 while (bfs(s, t)) 97 { 98 memcpy(cur, head, sizeof(head)); 99 max_flow += dfs(s, t, INT_MAX); 100 } 101 return max_flow; 102 } 103 104 int main() 105 { 106 int n, m, x, y; 107 while (cin >> n >> m) 108 { 109 dinic_init(); 110 int sum = 0; 111 for (int i = 1; i <= m; i++) 112 { 113 cin >> x; 114 add_edge(n + i, n + m + 1, x, 0); 115 } 116 for (int i = 1; i <= n; i++) 117 { 118 cin >> x; sum += x; 119 add_edge(0, i, x, 0); 120 cin >> y; 121 while (y--) 122 { 123 cin >> x; 124 add_edge(i, n + x, INF, 0); 125 } 126 } 127 int ans = dinic(0, n + m + 1); 128 cout << sum - ans << endl; 129 } 130 return 0; 131 }