最大流

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

 

 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 }
View Code

 

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 }
View Code

 

 

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 }
View Code

 

 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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

 

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 }
View Code

 

转载于:https://www.cnblogs.com/xFANx/p/9424517.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值