Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 70072 | Accepted: 27200 |
Description
Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network.
Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle.
Input
Output
Sample Input
5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
Sample Output
50
Source
題意描述:
現在有m個池塘(從1到m開始編號,1爲源點,m爲匯點),及n條水渠,給出這n條水渠所連接的池塘和所能流過的水量,求水渠中所能流過的水的最大容量.一道基礎的最大流題目。
對於網絡流最大流ford-fulkerson算法,如何理解呢?
先考慮這樣的貪心算法:
但事實上有更優的路線如下:
貪心算法得到的結果是10,而上圖得到的結果是11。爲了找出二者的區別,不妨來看看它們的流量的差。
通過對流量的差的觀察我們發現,我們可以將原先得到的流給推回去,而得到新的流。因此,可以試着在之前的貪心算法加上這一操作,將算法做出如下改進。
下面是此題的代碼:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 2e2 + 10;
struct edge {
int t, c, rev;
edge(int _t, int _c, int _rev) {
t = _t; c = _c; rev = _rev;
}
};
int n, m;
vector<edge> G[MAXN];
bool vis[MAXN];
int dfs(int v, int t, int f) {
if (v == t) return f;
vis[v] = true;
for (int i = 0; i < G[v].size(); ++i) {
edge& e = G[v][i];
if (!vis[e.t] && e.c > 0) {
int d = dfs(e.t, t, min(f, e.c));
if (d > 0) {
e.c -= d;
G[e.t][e.rev].c += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t) {
int flow = 0;
for (;;) {
memset(vis, 0, sizeof(vis));
int add = dfs(s, t, INF);
if (add == 0) return flow;
flow += add;
}
}
int main() {
#ifdef NIGHT_13
freopen("in.txt", "r", stdin);
#endif
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 0; i <= m; ++i) {
G[i].clear();
}
for (int i = 0, v, t, c; i < n; ++i) {
scanf("%d%d%d", &v, &t, &c);
G[v].push_back(edge(t, c, G[t].size()));
G[t].push_back(edge(v, 0, G[v].size() - 1));
}
printf("%d\n", max_flow(1, m));
}
return 0;
}
參考資料:《挑戰程序設計競賽》巫澤俊譯