1. 程式人生 > >hihocoder1394 網路流四·最小路徑覆蓋

hihocoder1394 網路流四·最小路徑覆蓋

思路:

拆點後進行最大二分匹配。點數 - 最大匹配數即是答案。

實現:

  1 #include <bits/stdc++.h>
  2 
  3 #define N (1005)
  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 for (int i = 1; i <= m; i++) 111 { 112 cin >> x >> y; 113 add_edge(x, n + y, 1, 0); 114 } 115 for (int i = 1; i <= n; i++) 116 add_edge(0, i, 1, 0); 117 for (int i = 1; i <= n; i++) 118 add_edge(i + n, 2 * n + 1, 1, 0); 119 cout << n - dinic(0, 2 * n + 1) << endl; 120 } 121 return 0; 122 }