【网络流24题 #03】最小路径覆盖问题
题目链接:最小路径覆盖问题
哇 卡在输出也是醉了
重要结论:最小路径覆盖数 = 结点数(拆成边之前) - 最大流
本题也是点拆边
有异曲同工之妙
void output(int x){ if(x >= S) return ; printf("%d ", x >> 1); for(int i = head[x]; i != -1; i = edge[i].next) if(!edge[i].w && edge[i].v < S) output(edge[i].v - 1); } …… for(int i = 1; i <= n; i++) fa[i] = i; for(int i = 0; i <= esize; i += 2) { if(!edge[i].w && edge[i].v < S && edge[i].u < S){ fa[find(edge[i].v >> 1)] = find(edge[i].u >> 1); } } for(int i = 1; i <= n; i++){ if(find(i) == i){ output(i << 1); printf("\n"); }
内心戏:(╯‵□′)╯︵┻━┻
悄咪咪:居然还打扰H神吃饭…
1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 #include <cstring> 5 #include <cmath> 6 using namespace std; 7 const int N = 4e4 + 5; 8 const int inf = 0x3f3f3f3f; 9 int n, m; 10 struct Edge{ 11 int u, v, w, next; 12 }edge[N << 1]; 13 int head[N], esize = -1; 14 bool vis[N]; 15 int next[N], fa[N]; 16 inline void addedge(int x, int y, int z){ 17 edge[++esize] = (Edge){x, y, z, head[x]}; 18 head[x] = esize; 19 edge[++esize] = (Edge){y, x, 0, head[y]}; 20 head[y] = esize; 21 } 22 queue<int> q; 23 int dep[N]; 24 int S, T; 25 26 bool bfs(){ 27 int fro; 28 q.push(S); 29 memset(dep, 0, sizeof(dep)); 30 dep[S] = 1; 31 while(!q.empty()){ 32 fro = q.front(); q.pop(); 33 for(int i = head[fro]; i != -1; i = edge[i].next){ 34 int vv = edge[i].v; 35 if(!dep[vv] && edge[i].w > 0){ 36 dep[vv] = dep[fro] + 1; 37 q.push(vv); 38 } 39 } 40 } 41 return dep[T]; 42 } 43 44 int dfs(int x, int rest){ 45 if(x == T || !rest) return rest; 46 for(int i = head[x], vv, ww, d; i != -1; i = edge[i].next){ 47 vv = edge[i].v, ww = edge[i].w; 48 if(dep[vv] != dep[x] + 1) continue; 49 d = dfs(vv, min(rest, ww)); 50 if(d > 0){ 51 edge[i].w -= d; 52 edge[i ^ 1].w += d; 53 return d; 54 } 55 } 56 return 0; 57 } 58 59 int dinic(){ 60 int ret = 0; 61 while(bfs()){ 62 ret += dfs(S, inf); 63 } 64 return ret; 65 } 66 67 int find(int x){ 68 return x == fa[x] ? x : fa[x] = find(fa[x]); 69 } 70 71 void output(int x){ 72 if(x >= S) return ; 73 printf("%d ", x >> 1); 74 for(int i = head[x]; i != -1; i = edge[i].next) 75 if(!edge[i].w && edge[i].v < S) output(edge[i].v - 1); 76 } 77 78 int main(){ 79 scanf("%d%d", &n, &m); 80 memset(head, -1, sizeof(head)); 81 memset(next, -1, sizeof(next)); 82 S = N - 3, T = N - 2; 83 for(int i = 1; i <= n; i++){ 84 addedge(S, i << 1, 1); 85 addedge(i << 1 | 1, T, 1); 86 } 87 for(int i = 1, x, y; i <= m; i++){ 88 addedge(x << 1, y << 1 | 1, 1); 89 } 90 int cnt = n - dinic(); 91 for(int i = 1; i <= n; i++) fa[i] = i; 92 for(int i = 0; i <= esize; i += 2) { 93 if(!edge[i].w && edge[i].v < S && edge[i].u < S){ 94 fa[find(edge[i].v >> 1)] = find(edge[i].u >> 1); 95 } 96 } 97 for(int i = 1; i <= n; i++){ 98 if(find(i) == i){ 99 output(i << 1); 100 printf("\n"); 101 } 102 } 103 printf("%d", cnt); 104 return 0; 105 }