[luoguP2764] 最小路径覆盖问题(最大流 || 二分图最大匹配)
可惜洛谷上没有special judge,不然用匈牙利也可以过的,因为匈牙利在增广上有一个顺序问题,所以没有special judge就过不了了。
好在这个题的测试数据比较特殊,如果是网络流的话按照顺序加边,就可以过。
最小不相交路径覆盖 = 总点数 - 最大匹配数
——代码
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #define N 20001 6 #define min(x, y) ((x) < (y) ? (x) : (y)) 7 #define max(x, y) ((x) > (y) ? (x) : (y)) 8 9 int n, m, cnt, sum, s, t; 10 int head[N], belong[N], to[N], next[N], val[N], suc[N], cur[N], dis[N]; 11 12 inline int read() 13 { 14 int x = 0, f = 1; 15 char ch = getchar(); 16 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 17 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 18 return x * f; 19 } 20 21 inline void add(int x, int y, int z) 22 { 23 to[cnt] = y; 24 val[cnt] = z; 25 next[cnt] = head[x]; 26 head[x] = cnt++; 27 } 28 29 inline bool bfs() 30 { 31 int i, u, v; 32 std::queue <int> q; 33 memset(dis, -1, sizeof(dis)); 34 q.push(s); 35 dis[s] = 0; 36 while(!q.empty()) 37 { 38 u = q.front(), q.pop(); 39 for(i = head[u]; i ^ -1; i = next[i]) 40 { 41 v = to[i]; 42 if(val[i] && dis[v] == -1) 43 { 44 dis[v] = dis[u] + 1; 45 if(v == t) return 1; 46 q.push(v); 47 } 48 } 49 } 50 return 0; 51 } 52 53 inline int dfs(int u, int maxflow) 54 { 55 if(u == t) return maxflow; 56 int i, v, d, ret = 0; 57 for(i = cur[u]; i ^ -1; i = next[i]) 58 { 59 v = to[i]; 60 if(val[i] && dis[v] == dis[u] + 1) 61 { 62 d = dfs(v, min(val[i], maxflow - ret)); 63 ret += d; 64 cur[u] = i; 65 val[i] -= d; 66 val[i ^ 1] += d; 67 if(d) suc[u] = v - n; 68 if(ret == maxflow) return ret; 69 } 70 } 71 return ret; 72 } 73 74 int main() 75 { 76 int i, j, x, y, now; 77 n = read(); 78 m = read(); 79 s = 0, t = (n << 1) + 1; 80 memset(head, -1, sizeof(head)); 81 for(i = 1; i <= m; i++) 82 { 83 x = read(); 84 y = read(); 85 add(x, y + n, 1); 86 add(y + n, x, 0); 87 } 88 for(i = 1; i <= n; i++) 89 { 90 add(s, i, 1); 91 add(i, s, 0); 92 add(i + n, t, 1); 93 add(t, i + n, 0); 94 } 95 while(bfs()) 96 { 97 for(i = s; i <= t; i++) cur[i] = head[i]; 98 sum += dfs(s, 1e9); 99 } 100 for(i = 1; i <= n; i++) 101 if(suc[i]) 102 { 103 now = i; 104 while(now) 105 { 106 printf("%d ", now); 107 x = suc[now]; 108 suc[now] = 0; 109 now = x; 110 } 111 puts(""); 112 } 113 printf("%d\n", n - sum); 114 return 0; 115 }