最大流
POJ 1273 模板题
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 typedef long long LL; 9 10 const int maxv = 1e3 + 10; 11 12 struct edge { 13 int to, cap, rev; 14 edge(int to, int cap, int rev): to(to), cap(cap), rev(rev) {} 15 }; 16 17 vector<edge> G[maxv]; 18 19 int level[maxv]; 20 int iter[maxv]; 21 22 void add_edge(int from, int to, int cap) { 23 G[from].push_back(edge(to, cap, G[to].size())); 24 G[to].push_back(edge(from, 0, G[from].size() - 1)); 25 } 26 27 void bfs(int s) { 28 memset(level, -1, sizeof(level)); 29 queue<int> que; 30 level[s] = 0; 31 que.push(s); 32 while (!que.empty()) { 33 int v = que.front(); que.pop(); 34 for (int i = 0; i < G[v].size(); i++) { 35 edge &e = G[v][i]; 36 if (e.cap > 0 && level[e.to] < 0) { 37 level[e.to] = level[v] + 1; 38 que.push(e.to); 39 } 40 } 41 } 42 } 43 44 int dfs(int v, int t, int f) { 45 if (v == t) return f; 46 for (int &i = iter[v]; i < G[v].size(); i++) { 47 edge &e = G[v][i]; 48 if (e.cap > 0 && level[v] < level[e.to]) { 49 int d = dfs(e.to, t, min(f, e.cap)); 50 if (d > 0) { 51 e.cap -= d; 52 G[e.to][e.rev].cap += d; 53 return d; 54 } 55 } 56 } 57 return 0; 58 } 59 60 int max_flow(int s, int t) { 61 int flow = 0; 62 while (1) { 63 bfs(s); 64 if (level[t] < 0) return flow; 65 memset(iter, 0, sizeof(iter)); 66 int f; 67 while ((f = dfs(s, t, INF)) > 0) { 68 flow += f; 69 } 70 } 71 } 72 73 74 int main() { 75 int n, m; 76 while (~scanf("%d%d", &m, &n)) { 77 for (int i = 0; i <= n + 1; i++) G[i].clear(); 78 int u, v, c; 79 for (int i = 0; i < m; i++) { 80 scanf("%d%d%d", &u, &v, &c); 81 add_edge(u, v, c); 82 } 83 int ans = 0; 84 ans = max_flow(1, n); 85 printf("%d\n", ans); 86 } 87 88 return 0; 89 }
POJ 2112 最小化最长边 floyd预处理 二分情况建图
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 typedef long long LL; 9 10 const int maxv = 300; 11 int graph[maxv][maxv]; 12 int K, C, M, V; 13 14 struct edge { 15 int to, cap, rev; 16 edge(int to, int cap, int rev): to(to), cap(cap), rev(rev) {} 17 }; 18 19 vector<edge> G[maxv]; 20 21 int level[maxv]; 22 int iter[maxv]; 23 24 void add_edge(int from, int to, int cap) { 25 G[from].push_back(edge(to, cap, G[to].size())); 26 G[to].push_back(edge(from, 0, G[from].size() - 1)); 27 } 28 29 void bfs(int s) { 30 memset(level, -1, sizeof(level)); 31 queue<int> que; 32 level[s] = 0; 33 que.push(s); 34 while (!que.empty()) { 35 int v = que.front(); que.pop(); 36 for (int i = 0; i < G[v].size(); i++) { 37 edge &e = G[v][i]; 38 if (e.cap > 0 && level[e.to] < 0) { 39 level[e.to] = level[v] + 1; 40 que.push(e.to); 41 } 42 } 43 } 44 } 45 46 int dfs(int v, int t, int f) { 47 if (v == t) return f; 48 for (int &i = iter[v]; i < G[v].size(); i++) { 49 edge &e = G[v][i]; 50 if (e.cap > 0 && level[v] < level[e.to]) { 51 int d = dfs(e.to, t, min(f, e.cap)); 52 if (d > 0) { 53 e.cap -= d; 54 G[e.to][e.rev].cap += d; 55 return d; 56 } 57 } 58 } 59 return 0; 60 } 61 62 int max_flow(int s, int t) { 63 int flow = 0; 64 while (1) { 65 bfs(s); 66 if (level[t] < 0) return flow; 67 memset(iter, 0, sizeof(iter)); 68 int f; 69 while ((f = dfs(s, t, INF)) > 0) { 70 flow += f; 71 } 72 } 73 } 74 75 bool ck(int limit) { 76 int s= V, t = V + 1; 77 for (int i = 0; i < V + 2; i++) G[i].clear(); 78 for (int i = 0; i < K; i++) add_edge(i, t, M); 79 for (int i = K; i < V; i++) add_edge(s, i, 1); 80 for (int i = 0; i < K; i++) { 81 for (int j = K; j < V; j++) { 82 if (graph[i][j] <= limit) add_edge(j, i, 1); 83 } 84 } 85 return max_flow(s, t) == C; 86 } 87 88 int solve() { 89 for (int k = 0; k < V; k++) { 90 for (int i = 0; i < V; i++) { 91 for (int j = 0; j < V; j++) { 92 graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]); 93 } 94 } 95 } 96 int l = 0, r = 200 * V; 97 while (r - l > 1) { 98 int mid = (r + l) >> 1; 99 (ck(mid) ? r : l) = mid; 100 } 101 return r; 102 } 103 104 105 int main() { 106 scanf("%d%d%d", &K, &C, &M); 107 V = K + C; 108 int t; 109 for (int i = 0; i < V; i++) { 110 for (int j = 0; j < V; j++) { 111 scanf("%d", &t); 112 graph[i][j] = t ? t : INF; 113 } 114 } 115 printf("%d\n", solve()); 116 return 0; 117 }
POJ 3204 求关键割边,即增加边容量可使得最大流流量增加的边数 从源汇分别做dfs以及判边满流
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 typedef long long LL; 9 10 const int maxv = 5e2 + 10; 11 const int maxe = 5e3 + 10; 12 13 bool Fw[maxv], Bk[maxv]; 14 int u[maxe], v[maxe]; 15 16 17 struct edge { 18 int to, cap, rev; 19 bool f; 20 edge(int to, int cap, int rev, bool f): to(to), cap(cap), rev(rev), f(f) {} 21 }; 22 23 vector<edge> G[maxv]; 24 25 int level[maxv]; 26 int iter[maxv]; 27 28 void add_edge(int from, int to, int cap) { 29 G[from].push_back(edge(to, cap, G[to].size(), true)); 30 G[to].push_back(edge(from, 0, G[from].size() - 1, false)); 31 } 32 33 void bfs(int s) { 34 memset(level, -1, sizeof(level)); 35 queue<int> que; 36 level[s] = 0; 37 que.push(s); 38 while (!que.empty()) { 39 int v = que.front(); que.pop(); 40 for (int i = 0; i < G[v].size(); i++) { 41 edge &e = G[v][i]; 42 if (e.cap > 0 && level[e.to] < 0) { 43 level[e.to] = level[v] + 1; 44 que.push(e.to); 45 } 46 } 47 } 48 } 49 50 int dfs(int v, int t, int f) { 51 if (v == t) return f; 52 for (int &i = iter[v]; i < G[v].size(); i++) { 53 edge &e = G[v][i]; 54 if (e.cap > 0 && level[v] < level[e.to]) { 55 int d = dfs(e.to, t, min(f, e.cap)); 56 if (d > 0) { 57 e.cap -= d; 58 G[e.to][e.rev].cap += d; 59 return d; 60 } 61 } 62 } 63 return 0; 64 } 65 66 int max_flow(int s, int t) { 67 int flow = 0; 68 while (1) { 69 bfs(s); 70 if (level[t] < 0) return flow; 71 memset(iter, 0, sizeof(iter)); 72 int f; 73 while ((f = dfs(s, t, INF)) > 0) { 74 flow += f; 75 } 76 } 77 } 78 79 void f(int x) { 80 Fw[x] = true; 81 for (int i = 0; i < G[x].size(); i++) { 82 edge &e = G[x][i]; 83 if (e.f && !Fw[e.to] && e.cap) { 84 f(e.to); 85 } 86 } 87 } 88 89 void b(int x) { 90 Bk[x] = true; 91 for (int i = 0; i < G[x].size(); i++) { 92 edge &e = G[x][i]; 93 if (!e.f && !Bk[e.to] && G[e.to][e.rev].cap) { 94 b(e.to); 95 } 96 } 97 } 98 99 int main() { 100 int n, m; 101 scanf("%d%d", &n, &m); 102 memset(Fw, false, sizeof(Fw)); memset(Bk, false, sizeof(Bk)); 103 for (int i = 0; i <= n + 1; i++) G[i].clear(); 104 int c; 105 for (int i = 0; i < m; i++) { 106 scanf("%d%d%d", &u[i], &v[i], &c); 107 108 add_edge(u[i], v[i], c); 109 } 110 max_flow(0, n - 1); 111 f(0); b(n - 1); 112 int ans = 0; 113 for (int i = 0; i < n; i++) { 114 for (int j = 0; j < G[i].size(); j++) { 115 edge &e = G[i][j]; 116 if (e.f && Fw[i] && Bk[e.to] && e.cap == 0) ans++; 117 } 118 } 119 printf("%d\n", ans); 120 return 0; 121 }
ZOJ 2532 同为求关键割边
POJ 2914 全局最小割 stoer_wagner算法
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define INF 0x3f3f3f3f 5 using namespace std; 6 typedef long long LL; 7 8 const int maxn = 5e2 + 10; 9 10 int G[maxn][maxn]; 11 int v[maxn]; 12 int w[maxn]; 13 bool visited[maxn]; 14 15 int stoer_wagner(int n) { 16 int min_cut = INF; 17 for (int i = 0; i < n; i++) { 18 v[i] = i; 19 } 20 while (n > 1) { 21 int pre = 0; 22 memset(visited, 0, sizeof(visited)); 23 memset(w, 0, sizeof(w)); 24 for (int i = 1; i < n; i++) { 25 int k = -1; 26 for (int j = 1; j < n; j++) { 27 if (!visited[v[j]]) { 28 w[v[j]] += G[v[pre]][v[j]]; 29 if (k == -1 || w[v[k]] < w[v[j]]) k = j; 30 } 31 } 32 visited[v[k]] = true; 33 if (i == n - 1) { 34 const int s = v[pre], t = v[k]; 35 min_cut = min(min_cut, w[t]); 36 for (int j = 0; j < n; j++) { 37 G[s][v[j]] += G[v[j]][t]; 38 G[v[j]][s] += G[v[j]][t]; 39 } 40 v[k] = v[--n]; 41 } 42 pre = k; 43 } 44 } 45 return min_cut; 46 } 47 48 int main() { 49 int n, m; 50 while (~scanf("%d%d", &n, &m)) { 51 memset(G, 0, sizeof(G)); 52 int u, v, w; 53 while (m--) { 54 scanf("%d%d%d", &u, &v, &w); 55 G[u][v] += w; 56 G[v][u] += w; 57 } 58 printf("%d\n", stoer_wagner(n)); 59 } 60 return 0; 61 }
SGU 194 有上下界的网络流模板题
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 typedef long long LL; 9 10 const int maxv = 1e3 + 10; 11 const int maxe = 4e4 + 10; 12 13 int in[maxv], out[maxv], lb[maxe]; 14 int u[maxe], v[maxe]; 15 int S, T; 16 int ans[maxe]; 17 18 struct edge { 19 int to, cap, rev; 20 edge(int to, int cap, int rev): to(to), cap(cap), rev(rev) {} 21 }; 22 23 vector<edge> G[maxv]; 24 25 int level[maxv]; 26 int iter[maxv]; 27 28 29 void add_edge(int from, int to, int cap) { 30 ans[++ans[0]] = G[from].size(); 31 G[from].push_back(edge(to, cap, G[to].size())); 32 G[to].push_back(edge(from, 0, G[from].size() - 1)); 33 } 34 35 void bfs(int s) { 36 memset(level, -1, sizeof(level)); 37 queue<int> que; 38 level[s] = 0; 39 que.push(s); 40 while (!que.empty()) { 41 int v = que.front(); que.pop(); 42 for (int i = 0; i < G[v].size(); i++) { 43 edge &e = G[v][i]; 44 if (e.cap > 0 && level[e.to] < 0) { 45 level[e.to] = level[v] + 1; 46 que.push(e.to); 47 } 48 } 49 } 50 } 51 52 int dfs(int v, int t, int f) { 53 if (v == t) return f; 54 for (int &i = iter[v]; i < G[v].size(); i++) { 55 edge &e = G[v][i]; 56 if (e.cap > 0 && level[v] < level[e.to]) { 57 int d = dfs(e.to, t, min(f, e.cap)); 58 if (d > 0) { 59 e.cap -= d; 60 G[e.to][e.rev].cap += d; 61 return d; 62 } 63 } 64 } 65 return 0; 66 } 67 68 int max_flow(int s, int t) { 69 int flow = 0; 70 while (1) { 71 bfs(s); 72 if (level[t] < 0) return flow; 73 memset(iter, 0, sizeof(iter)); 74 int f; 75 while ((f = dfs(s, t, INF)) > 0) { 76 flow += f; 77 } 78 } 79 } 80 81 void init(int n) { 82 S = 0, T = n + 1; 83 memset(out, 0, sizeof(out)); memset(in, 0, sizeof(in)); 84 memset(lb, 0, sizeof(lb)); ans[0] = 0; 85 for (int i = 0; i <= T; i++) G[i].clear(); 86 } 87 88 89 int main() { 90 int n, m; 91 int b, c; 92 scanf("%d%d", &n, &m); 93 init(n); 94 for (int i = 0; i < m; i++) { 95 scanf("%d%d%d%d", &u[i], &v[i], &b, &c); 96 out[u[i]] += b; 97 in[v[i]] += b; 98 lb[i] = b; 99 add_edge(u[i], v[i], c - b); 100 } 101 for (int i = 1; i <= n; i++) { 102 int dif = in[i] - out[i]; 103 if (dif > 0) { 104 add_edge(S, i, dif); 105 out[S] += dif; 106 } else if (dif < 0) { 107 add_edge(i, T, -dif); 108 } 109 } 110 int flow = max_flow(S, T); 111 if (flow != out[S]) { 112 puts("NO"); 113 } else { 114 puts("YES"); 115 for (int i = 0; i < m; i++) { 116 edge &e = G[u[i]][ans[i + 1]]; 117 printf("%d\n", lb[i] + G[v[i]][e.rev].cap); 118 } 119 } 120 121 122 return 0; 123 }
POJ 1815 求最小割点,要求字典序最小
做法:拆点,使得割点转化为割边。 然后枚举并在残余网络上做dfs。对于满流的i到i+N(即到自身)的边,dfs查看i到i+N是否有边,没有的话边对应了一个割点。要记住割完后把流量回退(i退回源,汇退回i+N)
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 typedef long long LL; 9 10 const int maxv = 2e2 + 10; 11 12 int N, S, T; 13 14 struct edge { 15 int to, cap, rev, flow; 16 edge(int to, int cap, int rev, int flow): to(to), cap(cap), rev(rev), flow(flow) {} 17 }; 18 19 vector<edge> G[maxv * 2]; 20 21 int kn[maxv][maxv]; 22 23 int level[maxv * 2]; 24 int iter[maxv * 2]; 25 int isf[maxv]; 26 bool vis[maxv * 2]; 27 28 void add_edge(int from, int to, int cap) { 29 G[from].push_back(edge(to, cap, G[to].size(), 0)); 30 G[to].push_back(edge(from, 0, G[from].size() - 1, 0)); 31 } 32 33 void bfs(int s) { 34 memset(level, -1, sizeof(level)); 35 queue<int> que; 36 level[s] = 0; 37 que.push(s); 38 while (!que.empty()) { 39 int v = que.front(); que.pop(); 40 for (int i = 0; i < G[v].size(); i++) { 41 edge &e = G[v][i]; 42 if ((e.cap - e.flow) > 0 && level[e.to] < 0) { 43 level[e.to] = level[v] + 1; 44 que.push(e.to); 45 } 46 } 47 } 48 } 49 50 int dfs(int v, int t, int f) { 51 if (v == t) return f; 52 for (int &i = iter[v]; i < G[v].size(); i++) { 53 edge &e = G[v][i]; 54 if ((e.cap - e.flow) > 0 && level[v] < level[e.to]) { 55 int d = dfs(e.to, t, min(f, (e.cap - e.flow))); 56 if (d > 0) { 57 e.flow += d; 58 G[e.to][e.rev].flow -= d; 59 return d; 60 } 61 } 62 } 63 return 0; 64 } 65 66 int max_flow(int s, int t) { 67 int flow = 0; 68 while (1) { 69 bfs(s); 70 if (level[t] < 0) return flow; 71 memset(iter, 0, sizeof(iter)); 72 int f; 73 while ((f = dfs(s, t, INF)) > 0) { 74 flow += f; 75 } 76 } 77 } 78 79 bool find(int s, int t) { 80 vis[s] = true; 81 if (s == t) return true; 82 for (int i = 0; i < G[s].size(); i++) { 83 edge &e = G[s][i]; 84 if (e.cap - e.flow && !vis[e.to]) { 85 if (find(e.to, t)) return true; 86 } 87 } 88 return false; 89 } 90 91 int main() { 92 93 scanf("%d%d%d", &N, &S, &T); 94 for (int i = 1; i <= N; i++) { 95 for (int j = 1; j <= N; j++) { 96 scanf("%d", &kn[i][j]); 97 } 98 } 99 for (int i = 1; i <= N; i++) { 100 isf[i] = G[i].size(); 101 add_edge(i, i + N, (i == S || i == T) ? INF : 1); 102 for (int j = i + 1; j <= N; j++) { 103 if (kn[i][j]) add_edge(i + N, j, INF), add_edge(j + N, i, INF); 104 } 105 } 106 int ans = max_flow(S, T + N); 107 if (ans == INF) { 108 puts("NO ANSWER!"); 109 } else { 110 printf("%d\n", ans); 111 for (int i = 1; i <= N && ans; i++) { 112 if (i == S || i == T) continue; 113 int tmp = isf[i]; 114 edge &e = G[i][tmp]; 115 if (e.cap == e.flow) { 116 memset(vis, false, sizeof(vis)); 117 if (!find(i, i + N)) { 118 memset(iter, 0, sizeof(iter)); bfs(i); dfs(i, S, INF); 119 memset(iter, 0, sizeof(iter)); bfs(T); dfs(T, i + N, INF); 120 printf("%d ", i); 121 } 122 } 123 } 124 puts(""); 125 } 126 return 0; 127 }
POJ 3084
有N个房间(0~N-1),其中一些门被入侵,已知一些门联通u和v(双向边),我们可以锁门使之变为单向边(u到v),求最少的锁门操作使目标门不被入侵。
显然求最小割, 则对于可锁上的门,v到u容量为1(使之最终对应最小割的边数),原图。什么标志着必然会被入侵?已被入侵的门与目标门联通(此时流量应为INF)。那么我们应当设置源点与被入侵门流量为INF,汇点为目标门。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 #define INF 0x3f3f3f 7 #define capType int 8 using namespace std; 9 typedef long long LL; 10 11 const int maxv = 100; 12 13 char str[10]; 14 15 struct edge { 16 int to, rev; 17 capType cap; 18 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 19 }; 20 21 22 vector<edge> G[maxv]; 23 24 25 int level[maxv]; 26 int iter[maxv]; 27 28 29 void add_edge(int from, int to, int cap) { 30 G[from].push_back(edge(to, cap, G[to].size())); 31 G[to].push_back(edge(from, 0, G[from].size() - 1)); 32 } 33 34 void bfs(int s) { 35 memset(level, -1, sizeof(level)); 36 level[s] = 0; 37 queue<int> que; 38 que.push(s); 39 while (!que.empty()) { 40 int v = que.front(); que.pop(); 41 for (int i = 0;i < G[v].size(); i++) { 42 edge &e = G[v][i]; 43 if (e.cap > 0 && level[e.to] < 0) { 44 level[e.to] = level[v] + 1; 45 que.push(e.to); 46 } 47 } 48 } 49 } 50 51 int dfs(int v, int t, int f) { 52 if (v == t) return f; 53 for (int &i = iter[v]; i < G[v].size(); i++) { 54 edge &e = G[v][i]; 55 if (e.cap && level[v] < level[e.to]) { 56 int d = dfs(e.to, t, min(f, e.cap)); 57 if (d > 0) { 58 e.cap -= d; 59 G[e.to][e.rev].cap += d; 60 return d; 61 } 62 } 63 } 64 return 0; 65 } 66 67 68 int max_flow(int s, int t) { 69 int flow = 0; 70 while (1) { 71 bfs(s); 72 if (level[t] < 0) return flow; 73 memset(iter, 0, sizeof(iter)); 74 int f; 75 while ((f = dfs(s, t, INF)) > 0) { 76 flow += f; 77 } 78 } 79 } 80 81 int main() { 82 int S; int T; int cnt; 83 int Te; scanf("%d", &Te); 84 while (Te--) { 85 scanf("%d%d", &cnt, &T); 86 S = cnt + 1; 87 int c; 88 for (int i = 0; i <= S; i++) G[i].clear(); 89 for (int i = 0; i < cnt; i++) { 90 scanf("%s", str); 91 if (str[0] == 'I') add_edge(S, i, INF); 92 scanf("%d", &c); 93 int u; 94 for (int j = 0; j < c; j++) { 95 scanf("%d", &u); 96 add_edge(i, u, INF); add_edge(u, i, 1); 97 } 98 } 99 int ans = max_flow(S, T); 100 if (ans >= INF) { 101 puts("PANIC ROOM BREACH"); 102 } else { 103 printf("%d\n", ans); 104 } 105 } 106 return 0; 107 }
POJ3469
在核A和核B组成的双核CPU上跑N个模块。块i在A上花费为Ai,B上花费为Bi。有M对需要交互的模块。如果某一对在不同核上运行,产生额外花费wi。求执行所有模块的花费。
乍一看以为是费用流。。。但事实上
用最小的费用将对象划分成两个集合的问题,常可以转换成最小割问题。
有了这个想法,构图就很容易了。
源点代表核A,汇点代表核B,构图。然后对于额外花费,只要对u,v连上双向边即可。最后求一个最小割
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 #define INF 0x3f3f3f 7 #define capType int 8 using namespace std; 9 typedef long long LL; 10 11 const int maxv = 2e4 + 10; 12 13 struct edge { 14 int to, rev; 15 capType cap; 16 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 17 }; 18 19 20 vector<edge> G[maxv]; 21 22 23 int level[maxv]; 24 int iter[maxv]; 25 26 27 void add_edge(int from, int to, int cap) { 28 G[from].push_back(edge(to, cap, G[to].size())); 29 G[to].push_back(edge(from, 0, G[from].size() - 1)); 30 } 31 32 void bfs(int s) { 33 memset(level, -1, sizeof(level)); 34 level[s] = 0; 35 queue<int> que; 36 que.push(s); 37 while (!que.empty()) { 38 int v = que.front(); que.pop(); 39 for (int i = 0;i < G[v].size(); i++) { 40 edge &e = G[v][i]; 41 if (e.cap > 0 && level[e.to] < 0) { 42 level[e.to] = level[v] + 1; 43 que.push(e.to); 44 } 45 } 46 } 47 } 48 49 int dfs(int v, int t, int f) { 50 if (v == t) return f; 51 for (int &i = iter[v]; i < G[v].size(); i++) { 52 edge &e = G[v][i]; 53 if (e.cap && level[v] < level[e.to]) { 54 int d = dfs(e.to, t, min(f, e.cap)); 55 if (d > 0) { 56 e.cap -= d; 57 G[e.to][e.rev].cap += d; 58 return d; 59 } 60 } 61 } 62 return 0; 63 } 64 65 66 int max_flow(int s, int t) { 67 int flow = 0; 68 while (1) { 69 bfs(s); 70 if (level[t] < 0) return flow; 71 memset(iter, 0, sizeof(iter)); 72 int f; 73 while ((f = dfs(s, t, INF)) > 0) { 74 flow += f; 75 } 76 } 77 } 78 79 int main() { 80 int N, M; 81 int S, T; 82 scanf("%d%d", &N, &M); 83 S = 0; T = N + 1; 84 int a, b, w; 85 for (int i = 1; i <= N; i++) { 86 scanf("%d%d", &a, &b); 87 add_edge(S, i, a); add_edge(i, T, b); 88 } 89 for (int i = 0; i < M; i++) { 90 scanf("%d%d%d", &a, &b, &w); 91 add_edge(a, b, w); add_edge(b, a, w); 92 } 93 printf("%d\n", max_flow(S, T)); 94 return 0; 95 }
POJ 3438 拆点加枚举
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 #include <cmath> 7 #define INF 0x3f3f3f3f 8 #define capType int 9 using namespace std; 10 typedef long long LL; 11 12 13 const int maxv = 2e2 + 10; 14 int x[maxv], y[maxv], n[maxv], m[maxv]; 15 int v[maxv][maxv]; 16 17 struct edge { 18 int to, rev; 19 capType cap; 20 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 21 }; 22 23 24 vector<edge> G[maxv]; 25 26 int level[maxv]; 27 int iter[maxv]; 28 29 30 void add_edge(int from, int to, int cap) { 31 G[from].push_back(edge(to, cap, G[to].size())); 32 G[to].push_back(edge(from, 0, G[from].size() - 1)); 33 } 34 35 void bfs(int s) { 36 memset(level, -1, sizeof(level)); 37 level[s] = 0; 38 queue<int> que; 39 que.push(s); 40 while (!que.empty()) { 41 int v = que.front(); que.pop(); 42 for (int i = 0;i < G[v].size(); i++) { 43 edge &e = G[v][i]; 44 if (e.cap > 0 && level[e.to] < 0) { 45 level[e.to] = level[v] + 1; 46 que.push(e.to); 47 } 48 } 49 } 50 } 51 52 int dfs(int v, int t, int f) { 53 if (v == t) return f; 54 for (int &i = iter[v]; i < G[v].size(); i++) { 55 edge &e = G[v][i]; 56 if (e.cap && level[v] < level[e.to]) { 57 int d = dfs(e.to, t, min(f, e.cap)); 58 if (d > 0) { 59 e.cap -= d; 60 G[e.to][e.rev].cap += d; 61 return d; 62 } 63 } 64 } 65 return 0; 66 } 67 68 69 int max_flow(int s, int t) { 70 int flow = 0; 71 while (1) { 72 bfs(s); 73 if (level[t] < 0) return flow; 74 memset(iter, 0, sizeof(iter)); 75 int f; 76 while ((f = dfs(s, t, INF)) > 0) { 77 flow += f; 78 } 79 } 80 } 81 82 83 double dist(int a, int b, int c, int d) { 84 return sqrt(1.0 * (a - c) * (a - c) + 1.0 * (b - d) * (b - d)); 85 } 86 87 int N, sum; 88 89 void init() { 90 for (int i = 0; i <= N + N; i++) G[i].clear(); 91 memset(v, 0, sizeof(v)); 92 sum = 0; 93 } 94 95 int main() { 96 int Te; 97 int S; 98 double dis; 99 scanf("%d", &Te); 100 while (Te--) { 101 scanf("%d%lf", &N, &dis); 102 init(); 103 for (int i = 0; i < N; i++) { 104 scanf("%d%d%d%d", &x[i], &y[i], &n[i], &m[i]); 105 sum += n[i]; 106 } 107 for (int i = 0; i < N; i++) { 108 for (int j = i + 1; j < N; j++) { 109 if (dist(x[i], y[i], x[j], y[j]) <= dis) { 110 v[i][++v[i][0]] = j; 111 v[j][++v[j][0]] = i; 112 } 113 } 114 } 115 bool flag = false; 116 S = N + N; 117 for (int T = 0; T < N; T++) { 118 for (int i = 0; i <= N + N; i++) G[i].clear(); 119 for (int i = 0; i < N; i++) { 120 add_edge(S, i, n[i]); 121 add_edge(i, i + N, m[i]); 122 for (int j = 1; j <= v[i][0]; j++) { 123 add_edge(i + N, v[i][j], INF); 124 // printf("there is a edge between %d and %d\n", i, v[i][j]); 125 } 126 } 127 int ans = max_flow(S, T); 128 if (ans == sum) { 129 if (flag) printf(" "); 130 printf("%d", T); 131 flag = true; 132 } 133 } 134 if (!flag) printf("-1"); 135 puts(""); 136 137 } 138 139 return 0; 140 }
SPOJ - COCONUTS 同POJ3469
用最小费用将对象划分成两个集合
1 #include <vector> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define capType int 7 #define INF 0x3f3f3f3f 8 using namespace std; 9 typedef long long LL; 10 11 const int maxv = 310; 12 13 struct edge { 14 int to, rev; 15 capType cap; 16 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 17 }; 18 19 vector<edge> G[maxv]; 20 21 int iter[maxv], level[maxv]; 22 23 void add_edge(int from, int to, capType cap) { 24 G[from].push_back(edge(to, cap, G[to].size())); 25 G[to].push_back(edge(from, 0, G[from].size() - 1)); 26 } 27 28 void bfs(int s) { 29 queue<int> que; que.push(s); 30 memset(level, -1, sizeof(level)); level[s] = 0; 31 while (!que.empty()) { 32 int v = que.front(); que.pop(); 33 for (int i = 0; i < G[v].size(); i++) { 34 edge &e = G[v][i]; 35 if (e.cap > 0 && level[e.to] < 0) { 36 level[e.to] = level[v] + 1; 37 que.push(e.to); 38 } 39 } 40 } 41 } 42 43 44 capType dfs(int v, int t, capType f) { 45 if (v == t) return f; 46 for (int &i = iter[v]; i < G[v].size(); i++) { 47 edge &e = G[v][i]; 48 if (e.cap > 0 && level[v] < level[e.to]) { 49 capType d = dfs(e.to, t, min(f, e.cap)); 50 if (d > 0) { 51 e.cap -= d; 52 G[e.to][e.rev].cap += d; 53 return d; 54 } 55 } 56 } 57 return 0; 58 } 59 60 capType max_flow(int s, int t) { 61 capType flow = 0; 62 while (1) { 63 bfs(s); 64 if (level[t] < 0) return flow; 65 memset(iter, 0, sizeof(iter)); 66 capType f; 67 while ((f = dfs(s, t, INF)) > 0) { 68 flow += f; 69 } 70 } 71 } 72 73 int main() { 74 int n, m; 75 while (scanf("%d%d", &n, &m), n || m) { 76 for (int i = 0; i <= n + 1; i++) G[i].clear(); 77 int tag; 78 for (int i = 1; i <= n; i++) { 79 scanf("%d", &tag); 80 add_edge(0, i, tag); add_edge(i, n + 1, !tag); 81 } 82 int u, v; 83 for (int i = 0; i < m; i++) { 84 scanf("%d%d", &u, &v); add_edge(u, v, 1); add_edge(v, u, 1); 85 } 86 printf("%d\n", max_flow(0, n + 1)); 87 } 88 return 0; 89 }
POJ 2987 最大权闭包模板题
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #define capType long long 8 #define INF 0x3f3f3f3f3f3f3f3f 9 using namespace std; 10 typedef long long LL; 11 12 const int maxv = 5e3 + 10; 13 14 struct edge { 15 int to, rev; 16 capType cap; 17 edge(int to, capType cap, int rev) : to(to), cap(cap), rev(rev) {} 18 }; 19 20 int level[maxv]; 21 int iter[maxv]; 22 vector<edge> G[maxv]; 23 24 void add_edge(int from, int to, int cap) { 25 G[from].push_back(edge(to, cap, G[to].size())); 26 G[to].push_back(edge(from, 0, G[from].size() - 1)); 27 } 28 29 void bfs(int s) { 30 memset(level, -1, sizeof(level)); level[s] = 0; 31 queue<int> que; que.push(s); 32 while (!que.empty()) { 33 int v = que.front(); que.pop(); 34 for (int i = 0; i < G[v].size(); i++) { 35 edge &e = G[v][i]; 36 if (e.cap > 0 && level[e.to] < 0) { 37 level[e.to] = level[v] + 1; 38 que.push(e.to); 39 } 40 } 41 } 42 } 43 44 capType dfs(int v, int t, capType f) { 45 if (v == t) { 46 return f; 47 } 48 for (int &i = iter[v]; i < G[v].size(); i++) { 49 edge &e = G[v][i]; 50 if (e.cap > 0 && level[v] < level[e.to]) { 51 capType d = dfs(e.to, t, min(f, e.cap)); 52 if (d > 0) { 53 e.cap -= d; 54 G[e.to][e.rev].cap += d; 55 return d; 56 } 57 } 58 } 59 return 0; 60 } 61 62 capType max_flow(int s, int t) { 63 capType flow = 0; 64 while (1) { 65 bfs(s); 66 if (level[t] < 0) return flow; 67 memset(iter, 0, sizeof(iter)); 68 capType f; 69 while ((f = dfs(s, t, INF)) > 0) flow += f; 70 } 71 } 72 73 int cnt, vis[maxv]; 74 75 void dfs(int v) { 76 ++cnt; 77 vis[v] = true; 78 for (int i = 0; i < G[v].size(); i++) { 79 edge &e = G[v][i]; 80 if (e.cap && !vis[e.to]) dfs(e.to); 81 } 82 } 83 84 LL sum, ans; 85 86 int main() { 87 // cout << INF << endl; 88 int n, m, w; 89 scanf("%d%d", &n, &m); 90 int S = 0; int T = n + 1; 91 for (int i = 1; i <= n; i++) { 92 scanf("%d", &w); 93 if (w > 0) { 94 sum += w; 95 add_edge(S, i, w); 96 } else if (w < 0) { 97 add_edge(i, T, -w); 98 } 99 } 100 for (int i = 0; i < m; i++) { 101 int u, v; 102 scanf("%d%d", &u, &v); 103 add_edge(u, v, INF); 104 } 105 ans = sum - max_flow(S, T); 106 dfs(S); 107 printf("%d %lld\n", cnt - 1, ans); 108 return 0; 109 }
ZOJ 2587 问最小割是否唯一
跑一遍最大流,然后从汇和源分别dfs,看是否有点从S 不可到达,从T不可到达,这个点必然可以属于S集或T集
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #define capType int 8 #define INF 0x3f3f3f3f 9 using namespace std; 10 typedef long long LL; 11 12 const int maxv = 5e3 + 10; 13 14 struct edge { 15 int to, rev; 16 int fd; 17 capType cap; 18 edge(int to, capType cap, int rev, int fd) : to(to), cap(cap), rev(rev), fd(fd) {} 19 }; 20 21 int level[maxv], iter[maxv]; 22 int vis[maxv], rvis[maxv]; 23 vector<edge> G[maxv]; 24 25 void add_edge(int from, int to, int cap) { 26 G[from].push_back(edge(to, cap, G[to].size(), 1)); 27 G[to].push_back(edge(from, 0, G[from].size() - 1, 0)); 28 } 29 30 void bfs(int s) { 31 memset(level, -1, sizeof(level)); level[s] = 0; 32 queue<int> que; que.push(s); 33 while (!que.empty()) { 34 int v = que.front(); que.pop(); 35 for (int i = 0; i < G[v].size(); i++) { 36 edge &e = G[v][i]; 37 if (e.cap > 0 && level[e.to] < 0) { 38 level[e.to] = level[v] + 1; 39 que.push(e.to); 40 } 41 } 42 } 43 } 44 45 capType dfs(int v, int t, capType f) { 46 if (v == t) { 47 return f; 48 } 49 for (int &i = iter[v]; i < G[v].size(); i++) { 50 edge &e = G[v][i]; 51 if (e.cap > 0 && level[v] < level[e.to]) { 52 capType d = dfs(e.to, t, min(f, e.cap)); 53 if (d > 0) { 54 e.cap -= d; 55 G[e.to][e.rev].cap += d; 56 return d; 57 } 58 } 59 } 60 return 0; 61 } 62 63 capType max_flow(int s, int t) { 64 capType flow = 0; 65 while (1) { 66 bfs(s); 67 if (level[t] < 0) return flow; 68 memset(iter, 0, sizeof(iter)); 69 capType f; 70 while ((f = dfs(s, t, INF)) > 0) flow += f; 71 } 72 } 73 74 75 76 void dfs(int v, int tag[]) { 77 tag[v] = true; 78 for (int i = 0; i < G[v].size(); i++) { 79 edge &e = G[v][i]; 80 if (e.cap && !tag[e.to] && e.fd) dfs(e.to, tag); 81 } 82 } 83 84 void rdfs(int v, int tag[]) { 85 tag[v] = true; 86 for (int i = 0; i < G[v].size(); i++) { 87 edge &e = G[v][i]; 88 if (!e.fd && !tag[e.to] && G[e.to][e.rev].cap) rdfs(e.to, tag); 89 } 90 } 91 92 void init(int n) { 93 memset(vis, 0, sizeof(vis)); memset(rvis, 0, sizeof(rvis)); 94 for (int i = 1; i <= n; i++) G[i].clear(); 95 } 96 97 LL sum, ans; 98 99 int main() { 100 int N, M, S, T; 101 while (scanf("%d%d%d%d", &N, &M, &S, &T), (N || M || S || T)) { 102 init(N); 103 int u, v, cost; 104 for (int i = 0; i < M; i++) { 105 scanf("%d%d%d", &u, &v, &cost); 106 add_edge(u, v, cost); 107 add_edge(v, u, cost); 108 } 109 max_flow(S, T); 110 dfs(S, vis); rdfs(T, rvis); 111 bool flag = true; 112 for (int i = 1; i <= N && flag; i++) { 113 if (!vis[i] && !rvis[i]) flag = false; 114 } 115 printf("%s\n", flag ? "UNIQUE" : "AMBIGUOUS"); 116 } 117 return 0; 118 }
POJ 2125 最小点权覆盖
题意
给出每个点删除入边的花费
给出每个点删除出边的花费
求问删除所有边的最小花费
输出删除边的操作
分析:
对于这个问题,我们可以先考虑二分图的最小点权覆盖
对于二分图,我们会建立源S和汇T,从S到S集连边为点权,从T集连边到T,容量也为该点点权。
原图中的边容量设置为无穷大,此时的最大流就是最小点权覆盖
考虑如何将本题转化为二分图的问题
由于每个点有两种操作,两类花费,我们可以拆点,使v属于S集,v+n属于T集。原图中(u,v)的边则变为(u, v + n)
那么S到S集中的点的容量应该怎么设置?
由于此时S集中的点只有出边,所有容量必然设置为点删除出边的花费。同理得知如何设置T集到T的边容量。
跑最大流可以得出花费。
接下来的问题是,我们在过程中做了什么操作?
只需要在残余网络上dfs一遍,我们就可以知道每个点属于哪个集合。
对于原S集中的点,如果不能遍历到,说明该点属于T集,那么该点割去了出边。
对于原T集中的点,如果可以遍历到,该点到T的边必然满流,也就该点对应的拆点前的点要割去入边
必然满流的原因是,假设不满流,则有S->v,v->T ==> S->T 与我们已经得到最小割矛盾,故得证
POJ 1149 合并点的经典建图
规则一:
如果几个结点的流量的来源完全相同,则可以将它们合并成一个。
规则二:如果几个结点的流量的去向完全相同,则可以把它们合并成一个。
规则三:如果从点u到点v有一条容量为INF的边,并且点v除了点u以外没有别的流量来源,则可以把这两个结点合并
1 #include <vector> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 typedef long long LL; 9 typedef int capType; 10 11 const int maxv = 2e2 + 10; 12 const int maxh = 1e3 + 10; 13 14 int N, M; 15 int pre[maxh], pig[maxh]; 16 17 struct edge { 18 int to, rev; 19 capType cap; 20 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 21 }; 22 23 24 vector<edge> G[maxv]; 25 int level[maxv], iter[maxv]; 26 27 28 void add_edge(int from, int to, capType cap) { 29 G[from].push_back(edge(to, cap, G[to].size())); 30 G[to].push_back(edge(from, 0, G[from].size() - 1)); 31 } 32 33 34 void bfs(int s) { 35 memset(level, -1, sizeof(level)); 36 level[s] = 0; 37 queue<int> que; 38 que.push(s); 39 while (!que.empty()) { 40 int v = que.front(); que.pop(); 41 for (int i = 0; i < G[v].size(); i++) { 42 edge &e = G[v][i]; 43 if (e.cap > 0 && level[e.to] < 0) { 44 level[e.to] = level[v] + 1; 45 que.push(e.to); 46 } 47 } 48 } 49 } 50 51 capType dfs(int v, int t, int f) { 52 if (v == t) return f; 53 for (int &i = iter[v]; i < G[v].size(); i++) { 54 edge &e = G[v][i]; 55 if (e.cap > 0 && level[v] < level[e.to]) { 56 capType d = dfs(e.to, t, min(f, e.cap)); 57 if (d > 0) { 58 e.cap -= d; 59 G[e.to][e.rev].cap += d; 60 return d; 61 } 62 } 63 } 64 return 0; 65 } 66 67 capType max_flow(int s, int t) { 68 capType flow = 0; 69 while (1) { 70 bfs(s); 71 if (level[t] < 0) return flow; 72 memset(iter, 0, sizeof(iter)); 73 capType f; 74 while ((f = dfs(s, t, INF)) > 0) flow += f; 75 } 76 } 77 78 79 int main() { 80 memset(pre, 0, sizeof(pre)); 81 scanf("%d%d", &M, &N); 82 int S, T; 83 S = 0; T = N + 1; 84 for (int i = 1; i <= M; i++) { 85 scanf("%d", &pig[i]); 86 } 87 int cnt, t, sum; 88 for (int i = 1; i <= N; i++) { 89 scanf("%d", &cnt); 90 sum = 0; 91 for (int j = 1; j <= cnt; j++) { 92 scanf("%d", &t); 93 if (pre[t]) { 94 add_edge(pre[t], i, INF); 95 } else { 96 sum += pig[t]; 97 } 98 pre[t] = i; 99 } 100 scanf("%d", &cnt); 101 add_edge(i, T, cnt); 102 add_edge(S, i, sum); 103 } 104 capType ans = max_flow(S, T); 105 printf("%d\n", ans); 106 return 0; 107 }
POJ 1637 求混合图欧拉回路
为无向图设置方向(随意),统计所有结点的出入度
每个点的出入度差值必须为偶数
设置源汇,对我们设置方向的边构图(容量为一)。对每个点,若出度大于入度,从原点连(差值/2);若入度大于出度,连(-差值/2)到汇
判断是否满流
若需要求回路,将我们设置方向的边反向即可
1 #include <vector> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 typedef long long LL; 9 typedef int capType; 10 11 const int maxv = 2e2 + 10; 12 13 int in[maxv], out[maxv]; 14 15 struct edge { 16 int to, rev; 17 capType cap; 18 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 19 }; 20 21 22 vector<edge> G[maxv]; 23 int level[maxv], iter[maxv]; 24 25 26 void add_edge(int from, int to, capType cap) { 27 G[from].push_back(edge(to, cap, G[to].size())); 28 G[to].push_back(edge(from, 0, G[from].size() - 1)); 29 } 30 31 32 void bfs(int s) { 33 memset(level, -1, sizeof(level)); 34 level[s] = 0; 35 queue<int> que; 36 que.push(s); 37 while (!que.empty()) { 38 int v = que.front(); que.pop(); 39 for (int i = 0; i < G[v].size(); i++) { 40 edge &e = G[v][i]; 41 if (e.cap > 0 && level[e.to] < 0) { 42 level[e.to] = level[v] + 1; 43 que.push(e.to); 44 } 45 } 46 } 47 } 48 49 capType dfs(int v, int t, int f) { 50 if (v == t) return f; 51 for (int &i = iter[v]; i < G[v].size(); i++) { 52 edge &e = G[v][i]; 53 if (e.cap > 0 && level[v] < level[e.to]) { 54 capType d = dfs(e.to, t, min(f, e.cap)); 55 if (d > 0) { 56 e.cap -= d; 57 G[e.to][e.rev].cap += d; 58 return d; 59 } 60 } 61 } 62 return 0; 63 } 64 65 capType max_flow(int s, int t) { 66 capType flow = 0; 67 while (1) { 68 bfs(s); 69 if (level[t] < 0) return flow; 70 memset(iter, 0, sizeof(iter)); 71 capType f; 72 while ((f = dfs(s, t, INF)) > 0) flow += f; 73 } 74 } 75 76 void init(int n) { 77 for (int i = 0; i <= n + 1; i++) G[i].clear(); 78 memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); 79 } 80 81 82 int main() { 83 int Te, n, m; 84 scanf("%d", &Te); 85 while (Te--) { 86 scanf("%d%d", &n, &m); 87 init(n); 88 int u, v, dir; 89 for (int i = 0; i < m; i++) { 90 scanf("%d%d%d", &u, &v, &dir); 91 out[u]++; in[v]++; 92 if (dir == 0) add_edge(u, v, 1); 93 } 94 bool flag = true; 95 int S = 0, T = n + 1; 96 int sum = 0; 97 for (int i = 1; i <= n && flag; i++) { 98 if (out[i] - in[i] > 0) { 99 int t = (out[i] - in[i]) / 2; 100 sum += t; 101 add_edge(S, i, t); 102 } else if (in[i] - out[i] > 0) { 103 add_edge(i, T, (in[i] - out[i]) / 2); 104 } 105 if ((out[i] - in[i]) & 1) flag = false; 106 } 107 if (!flag) { 108 puts("impossible"); 109 } else { 110 int ans = max_flow(S, T); 111 if (ans == sum) { 112 puts("possible"); 113 } else { 114 puts("impossible"); 115 } 116 } 117 } 118 return 0; 119 }
POJ 3281
N头牛F种食物D种饮料
每头牛有喜欢的食物饮料,每种食物或饮料分配给一头牛,问最多有多少头牛能同时得到喜欢的食物和饮料
增加源汇点,把牛拆点, 边权为1,表示一头牛不会被分配多组,牛和食物的匹配,饮料和牛的匹配。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 #define INF 0x3f3f3f3f 7 #define capType int 8 using namespace std; 9 typedef long long LL; 10 11 const int maxv = 1e3 + 10; 12 13 struct edge { 14 int to, rev; 15 capType cap; 16 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 17 }; 18 19 int level[maxv]; 20 int iter[maxv]; 21 vector<edge> G[maxv]; 22 23 void add_edge(int from, int to, capType cap) { 24 G[from].push_back(edge(to, cap, G[to].size())); 25 G[to].push_back(edge(from, 0, G[from].size() - 1)); 26 } 27 28 void bfs(int s) { 29 memset(level, -1, sizeof(level)); 30 level[s] = 0; 31 queue<int> que; 32 que.push(s); 33 while (!que.empty()) { 34 int v = que.front(); que.pop(); 35 for (int i = 0; i < G[v].size(); i++) { 36 edge &e = G[v][i]; 37 if (e.cap > 0 && level[e.to] < 0) { 38 level[e.to] = level[v] + 1; 39 que.push(e.to); 40 } 41 } 42 } 43 } 44 45 46 capType dfs(int v, int t, capType f) { 47 if (v == t) return f; 48 for (int &i = iter[v]; i < G[v].size(); i++) { 49 edge &e = G[v][i]; 50 if (e.cap > 0 && level[v] < level[e.to]) { 51 capType d = dfs(e.to, t, min(f, e.cap)); 52 if (d > 0) { 53 e.cap -= d; 54 G[e.to][e.rev].cap += d; 55 return d; 56 } 57 } 58 } 59 return 0; 60 } 61 62 capType max_flow(int s, int t) { 63 capType flow = 0; 64 while (1) { 65 bfs(s); 66 if (level[t] < 0) return flow; 67 memset(iter, 0, sizeof(iter)); 68 int f; 69 while ((f = dfs(s, t, INF)) > 0) { 70 flow += f; 71 } 72 } 73 } 74 75 76 int main() { 77 int N, F, D; int S, T; 78 int f, d; 79 scanf("%d%d%d", &N, &F, &D); 80 S = 0; T = N + N + F + D + 1; 81 for (int i = 1; i <= F; i++) add_edge(S, N + N + i, 1); 82 for (int i = 1; i <= D; i++) add_edge(N + N + F + i, T, 1); 83 for (int i = 1; i <= N; i++) { 84 add_edge(i, i + N, 1); 85 scanf("%d%d", &f, &d); 86 int t; 87 for (int j = 0; j < f; j++) { 88 scanf("%d", &t); 89 add_edge(t + N + N, i, 1); 90 } 91 for (int j = 0; j < d; j++) { 92 scanf("%d", &t); 93 add_edge(i + N, t + N + N + F, 1); 94 } 95 } 96 printf("%d\n", max_flow(S, T)); 97 return 0; 98 }
ZOJ 2760 求互不相交的最短路的数目(起点终点相同时输出inf)
每条路最多经过一次,显然可以借助网络流,限制边流量为1,问题在如何构图使得图中的s-t路都是最短路?
分别从起点,终点(反向图)跑一边最短路,检查边,如果两端的值加上边权为最短路值,那么该边在某条最短路上,加入网络。
1 #include <vector> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define capType int 7 #define INF 0x3f3f3f3f 8 using namespace std; 9 typedef long long LL; 10 11 const int maxv = 110; 12 int mp[maxv][maxv]; 13 14 struct edge { 15 int to, cost; 16 edge(int to, int cost): to(to), cost(cost) {} 17 }; 18 typedef pair<int, int> P; 19 20 int V; 21 vector<edge> G1[maxv]; 22 vector<edge> G2[maxv]; 23 int d1[maxv], d2[maxv]; 24 25 void dij(int s, int *d, vector<edge> G[]) { 26 //memset(d, INF, sizeof(d)); 27 fill(d, d + V + 1, INF); 28 d[s] = 0; 29 priority_queue<P, vector<P>, greater<P> > que; 30 que.push(P(0, s)); 31 while (!que.empty()) { 32 P p = que.top(); que.pop(); 33 int v = p.second; 34 if (d[v] < p.first) continue; 35 for (int i = 0; i < G[v].size(); i++) { 36 edge &e = G[v][i]; 37 if (d[e.to] > d[v] + e.cost) { 38 d[e.to] = d[v] + e.cost; 39 que.push(P(d[e.to], e.to)); 40 } 41 } 42 } 43 } 44 45 struct _edge { 46 int to, rev; 47 capType cap; 48 _edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 49 }; 50 51 vector<_edge> _G[maxv]; 52 int level[maxv]; 53 int iter[maxv]; 54 55 void add_edge(int from, int to, int cap) { 56 _G[from].push_back(_edge(to, cap, _G[to].size())); 57 _G[to].push_back(_edge(from, 0, _G[from].size() - 1)); 58 } 59 60 void bfs(int s) { 61 memset(level, -1, sizeof(level)); 62 level[s] = 0; 63 queue<int> que; 64 que.push(s); 65 while (!que.empty()) { 66 int v = que.front(); que.pop(); 67 for (int i = 0; i < _G[v].size(); i++) { 68 _edge &e = _G[v][i]; 69 if (e.cap > 0 && level[e.to] < 0) { 70 level[e.to] = level[v] + 1; 71 que.push(e.to); 72 } 73 } 74 } 75 } 76 77 capType dfs(int v, int t, int f) { 78 if (v == t) return f; 79 for (int &i = iter[v]; i < _G[v].size(); i++) { 80 _edge &e = _G[v][i]; 81 if (e.cap && level[v] < level[e.to]) { 82 capType d = dfs(e.to, t, min(f, e.cap)); 83 if (d > 0) { 84 e.cap -= d; 85 _G[e.to][e.rev].cap += d; 86 return d; 87 } 88 } 89 } 90 return 0; 91 } 92 93 capType max_flow(int s, int t) { 94 capType flow = 0; 95 while (1) { 96 bfs(s); 97 if (level[t] < 0) return flow; 98 memset(iter, 0, sizeof(iter)); 99 capType f; 100 while ((f = dfs(s, t, INF)) > 0) { 101 flow += f; 102 } 103 } 104 } 105 106 int main() { 107 int tmp; 108 int S, T; 109 while (~scanf("%d", &V)) { 110 for (int i = 0; i <= V + 1; i++) G1[i].clear(), G2[i].clear(), _G[i].clear(); 111 for (int i = 0; i < V; i++) { 112 for (int j = 0; j < V; j++) { 113 scanf("%d", &mp[i][j]); 114 if (mp[i][j] >= 0 && i != j) { 115 G1[i].push_back(edge(j, mp[i][j])); 116 G2[j].push_back(edge(i, mp[i][j])); 117 } 118 } 119 } 120 scanf("%d%d", &S, &T); 121 if (S == T) { 122 puts("inf"); 123 } else { 124 dij(S, d1, G1); 125 dij(T, d2, G2); 126 for (int i = 0; i < V; i++) { 127 for (int j = 0; j < V; j++) { 128 if (i == j || mp[i][j] == -1) continue; 129 if (d1[i] + d2[j] + mp[i][j] == d1[T]) { 130 add_edge(i, j, 1); 131 } 132 } 133 } 134 printf("%d\n", max_flow(S, T)); 135 } 136 137 } 138 return 0; 139 }
URAL 1277 无向图点带权的点联通问题
给定点数变数,艺术馆和贼窝。警察需要截断贼窝到艺术馆的路,当驻守一个点时,需要警力xi人,已知不能驻守在艺术馆或贼窝,求用已知警力能否完成任务
拆点求最小割即可
备注:1、若求无向图的边联通度:任选一点固定为源,枚举汇点求最小割,取最小值。
2、若求无向图的点联通度:拆点,限制点容量为1,以最小度顶点为源,枚举汇点求最小割,取最小值。
1 #include <vector> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define capType int 7 #define INF 0x3f3f3f3f 8 using namespace std; 9 typedef long long LL; 10 11 const int maxv = 210; 12 13 struct edge { 14 int to, rev; 15 capType cap; 16 edge(int to, capType cap, int rev): to(to), cap(cap), rev(rev) {} 17 }; 18 19 vector<edge> G[maxv]; 20 21 int iter[maxv], level[maxv]; 22 23 void add_edge(int from, int to, int cap) { 24 G[from].push_back(edge(to, cap, G[to].size())); 25 G[to].push_back(edge(from, 0, G[from].size() - 1)); 26 } 27 28 void bfs(int s) { 29 queue<int> que; que.push(s); 30 memset(level, -1, sizeof(level)); level[s] = 0; 31 while (!que.empty()) { 32 int v = que.front(); que.pop(); 33 for (int i = 0; i < G[v].size(); i++) { 34 edge &e = G[v][i]; 35 if (e.cap > 0 && level[e.to] < 0) { 36 level[e.to] = level[v] + 1; 37 que.push(e.to); 38 } 39 } 40 } 41 } 42 43 44 capType dfs(int v, int t, capType f) { 45 if (v == t) return f; 46 for (int &i = iter[v]; i < G[v].size(); i++) { 47 edge &e = G[v][i]; 48 if (e.cap > 0 && level[v] < level[e.to]) { 49 capType d = dfs(e.to, t, min(f, e.cap)); 50 if (d > 0) { 51 e.cap -= d; 52 G[e.to][e.rev].cap += d; 53 return d; 54 } 55 } 56 } 57 return 0; 58 } 59 60 capType max_flow(int s, int t) { 61 capType flow = 0; 62 while (1) { 63 bfs(s); 64 if (level[t] < 0) return flow; 65 memset(iter, 0, sizeof(iter)); 66 capType f; 67 while ((f = dfs(s, t, INF)) > 0) { 68 flow += f; 69 } 70 } 71 } 72 73 int main() { 74 int FLOW, N, M, S, F, t, u, v; 75 scanf("%d", &FLOW); 76 scanf("%d%d%d%d", &N, &M, &S, &F); 77 for (int i = 1; i <= N; i++) { 78 scanf("%d", &t); 79 add_edge(i, i + N, t); 80 } 81 for (int i = 0; i < M; i++) { 82 scanf("%d%d", &u, &v); 83 add_edge(u + N, v, INF); add_edge(v + N, u, INF); 84 } 85 int ans = ((S == F) ? INF : max_flow(S + N, F)); 86 // printf("%d\n", ans); 87 printf("%s\n", (FLOW >= ans) ? "YES" : "NO"); 88 return 0; 89 }