UVa 1440:Inspection(带下界的最小流)***
https://vjudge.net/problem/UVA-1440
题意:给出一个图,要求每条边都必须至少走一次,问最少需要一笔画多少次。
思路:看了好久才勉强看懂模板。良心推荐:学习地址。
看完这个大概就能懂了。
那条T->S的边的反向边的流量就是可行流的流量。
最小流就是去掉新的源点和新的汇点(保证必要弧)和T->S边后,从T往S跑最大流(尽量退流),最小流的答案就是原来T->S的反向边流量 - 第二次最大流的流量。
最大流就是去掉新的源点和新的汇点之后,再跑一遍最大流得到的就是答案。
最小流这里后面看别人的发现别人是先跑一遍(SS->ST)最大流,然后再连<T,S>边,再跑一遍(SS->ST)最大流。然而论文里面是先连<T,S>边,跑一遍(SS->ST)最大流,然后删掉<T,S>边和所有与SS、ST相连的边,跑一遍(T->S)的最大流。
看了N久还是不能完全理解。
记得多组数组!!!WA了一晚上。
写法一:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define N 210 4 #define INF 0x3f3f3f3f 5 struct Edge { 6 int u, v, nxt, cap; 7 } edge[N*N]; 8 int head[N], tot, dis[N], cur[N], pre[N], gap[N], in[N], out[N], S, T, SS, ST; 9 10 void Add(int u, int v, int cap) { 11 edge[tot].u = u, edge[tot].v = v, edge[tot].nxt = head[u], edge[tot].cap = cap, head[u] = tot++; 12 edge[tot].u = v, edge[tot].v = u, edge[tot].nxt = head[v], edge[tot].cap = 0, head[v] = tot++; 13 } 14 15 int BFS(int T) { 16 memset(dis, INF, sizeof(dis)); 17 memset(gap, 0, sizeof(gap)); 18 memcpy(cur, head, sizeof(cur)); 19 dis[T] = 0, gap[0]++; 20 queue<int> que; que.push(T); 21 while(!que.empty()) { 22 int u = que.front(); que.pop(); 23 for(int i = head[u]; ~i; i = edge[i].nxt) { 24 int v = edge[i].v; 25 if(dis[v] == INF) { 26 dis[v] = dis[u] + 1; 27 gap[dis[v]]++; 28 que.push(v); 29 } 30 } 31 } 32 } 33 34 int ISAP(int S, int T, int n) { 35 BFS(T); 36 int u = pre[S] = S, i, index, flow, ans = 0; 37 while(dis[S] < n) { 38 if(u == T) { 39 flow = INF; 40 for(i = S; i != T; i = edge[cur[i]].v) 41 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i; 42 for(i = S; i != T; i = edge[cur[i]].v) 43 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow; 44 ans += flow, u = index; 45 } 46 for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + 1 == dis[u]) break; 47 if(~i) { 48 cur[u] = i; pre[edge[i].v] = u; u = edge[i].v; 49 } else { 50 if(--gap[dis[u]] == 0) break; 51 int md = n; 52 for(int i = head[u]; ~i; i = edge[i].nxt) 53 if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i; 54 gap[dis[u] = md + 1]++; 55 u = pre[u]; 56 } 57 } 58 return ans; 59 } 60 61 void Delete() { 62 for(int i = head[SS]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0; 63 for(int i = head[ST]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0; 64 edge[tot-1].cap = edge[(tot-1)^1].cap = 0; 65 } 66 67 void Update(int n) { 68 for(int u = 1; u <= n; u++) { 69 for(int i = head[u]; ~i; i = edge[i].nxt) { 70 if(edge[i].v == S || edge[i].v == T || (i & 1)) continue; 71 edge[i^1].cap++; 72 } 73 } 74 } 75 76 void Dfs(int u) { 77 for(int i = head[u]; ~i; i = edge[i].nxt) { 78 int v = edge[i].v; 79 if(i & 1 || !edge[i^1].cap || v == S || v == T || v == SS || v == ST) continue; 80 edge[i^1].cap--; 81 printf(" %d", v); 82 Dfs(v); 83 break; 84 } 85 } 86 87 int main() { 88 int n; 89 while(~scanf("%d", &n)) { 90 memset(head, -1, sizeof(head)); tot = 0; 91 memset(out, 0, sizeof(out)); memset(in, 0, sizeof(in)); 92 S = n + 1, T = n + 2, SS = n + 3, ST = n + 4; 93 for(int i = 1; i <= n; i++) { 94 int k; scanf("%d", &k); 95 while(k--) { 96 int x; scanf("%d", &x); 97 out[i]++; in[x]++; 98 Add(i, x, INF); 99 } 100 } 101 for(int i = 1; i <= n; i++) { 102 if(!out[i]) Add(i, T, INF); 103 if(!in[i]) Add(S, i, INF); 104 int deg = in[i] - out[i]; 105 if(deg > 0) Add(SS, i, deg); 106 else if(deg < 0) Add(i, ST, -deg); 107 } 108 Add(T, S, INF); 109 ISAP(SS, ST, ST + 1); 110 int ans = edge[tot-1].cap; 111 Delete(); 112 ans -= ISAP(T, S, T + 1); 113 printf("%d\n", ans); 114 Update(n); 115 int cur = head[S]; 116 for(int k = 1; k <= ans; k++) { 117 for(int i = cur; ~i; i = edge[i].nxt) { 118 if(!(i & 1) && edge[i^1].cap) { 119 int v = edge[i].v; 120 edge[i^1].cap--; 121 printf("%d", v); 122 Dfs(edge[i].v); 123 puts(""); 124 cur = i; 125 break; 126 } 127 } 128 } 129 } 130 return 0; 131 }
写法二:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define N 210 4 #define INF 0x3f3f3f3f 5 struct Edge { 6 int u, v, nxt, cap; 7 } edge[N*N]; 8 int head[N], tot, dis[N], cur[N], pre[N], gap[N], in[N], out[N], S, T, SS, ST, n; 9 10 void Add(int u, int v, int cap) { 11 edge[tot].u = u, edge[tot].v = v, edge[tot].nxt = head[u], edge[tot].cap = cap, head[u] = tot++; 12 edge[tot].u = v, edge[tot].v = u, edge[tot].nxt = head[v], edge[tot].cap = 0, head[v] = tot++; 13 } 14 15 int BFS(int T) { 16 memset(dis, INF, sizeof(dis)); 17 memset(gap, 0, sizeof(gap)); 18 memcpy(cur, head, sizeof(cur)); 19 dis[T] = 0, gap[0]++; 20 queue<int> que; que.push(T); 21 while(!que.empty()) { 22 int u = que.front(); que.pop(); 23 for(int i = head[u]; ~i; i = edge[i].nxt) { 24 int v = edge[i].v; 25 if(dis[v] == INF) { 26 dis[v] = dis[u] + 1; 27 gap[dis[v]]++; 28 que.push(v); 29 } 30 } 31 } 32 } 33 34 int ISAP(int S, int T, int n) { 35 BFS(T); 36 int u = pre[S] = S, i, index, flow, ans = 0; 37 while(dis[S] < n) { 38 if(u == T) { 39 flow = INF; 40 for(i = S; i != T; i = edge[cur[i]].v) 41 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i; 42 for(i = S; i != T; i = edge[cur[i]].v) 43 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow; 44 ans += flow, u = index; 45 } 46 for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + 1 == dis[u]) break; 47 if(~i) { 48 cur[u] = i; pre[edge[i].v] = u; u = edge[i].v; 49 } else { 50 if(--gap[dis[u]] == 0) break; 51 int md = n; 52 for(int i = head[u]; ~i; i = edge[i].nxt) 53 if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i; 54 gap[dis[u] = md + 1]++; 55 u = pre[u]; 56 } 57 } 58 return ans; 59 } 60 61 void Delete() { 62 for(int i = head[SS]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0; 63 for(int i = head[ST]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0; 64 edge[tot-1].cap = edge[(tot-1)^1].cap = 0; 65 } 66 67 void Update(int n) { 68 for(int u = 1; u <= n; u++) { 69 for(int i = head[u]; ~i; i = edge[i].nxt) { 70 if(edge[i].v == S || edge[i].v == T || (i & 1)) continue; 71 edge[i^1].cap++; 72 } 73 } 74 } 75 76 void Dfs(int u) { 77 for(int i = head[u]; ~i; i = edge[i].nxt) { 78 int v = edge[i].v; 79 if(i & 1 || !edge[i^1].cap || v > n) continue; 80 edge[i^1].cap--; 81 printf(" %d", v); 82 Dfs(v); break; 83 } 84 } 85 86 void Solve() { 87 for(int u = 1; u <= n; u++) { 88 for(int i = head[u]; ~i; i = edge[i].nxt) { 89 int v = edge[i].v; 90 if(i & 1) continue; 91 edge[i^1].cap++; 92 } 93 } 94 for(int i = head[S]; ~i; i = edge[i].nxt) { 95 if(i & 1) continue; 96 while(edge[i^1].cap) { 97 edge[i^1].cap--; 98 int v = edge[i].v; 99 printf("%d", v); 100 Dfs(v); puts(""); 101 } 102 } 103 } 104 105 int main() { 106 while(~scanf("%d", &n)) { 107 memset(head, -1, sizeof(head)); tot = 0; 108 memset(out, 0, sizeof(out)); memset(in, 0, sizeof(in)); 109 S = n + 1, T = n + 2, SS = n + 3, ST = n + 4; 110 for(int i = 1; i <= n; i++) { 111 int k; scanf("%d", &k); 112 while(k--) { 113 int x; scanf("%d", &x); 114 out[i]++; in[x]++; 115 Add(i, x, INF); 116 } 117 } 118 for(int i = 1; i <= n; i++) { 119 if(!out[i]) Add(i, T, INF); 120 if(!in[i]) Add(S, i, INF); 121 int deg = in[i] - out[i]; 122 if(deg > 0) Add(SS, i, deg); 123 else if(deg < 0) Add(i, ST, -deg); 124 } 125 ISAP(SS, ST, ST + 1); 126 Add(T, S, INF); 127 int ans = ISAP(SS, ST, ST + 1); 128 printf("%d\n", ans); 129 Solve(); 130 } 131 return 0; 132 }