網絡流: dinic
題目描述
每當農民約翰的田地下雨,池塘就形成在Bessie最喜歡的三葉草補丁上。這意味着三葉草被水覆蓋了一段時間,需要相當長的時間才能再生。因此,農民約翰已經建立了一套排水溝,使Bessie的苜蓿補丁從來沒有覆蓋在水中。取而代之的是,水被排入附近的溪流中。作爲一名ACE工程師,農民約翰也在每個溝的開始安裝了調節器,所以他可以控制水流到溝裏的速率。
農場主約翰不僅知道每條溝每分鐘能輸送多少加侖水,而且知道溝渠的精確佈局,這些溝渠從池塘中流入,相互流入,並在一個潛在的複雜網絡中流動。
考慮到所有這些信息,確定水可以從池塘中運輸到河流中的最大速率。對於任何給定的溝渠,水流只有一個方向,但可能有一種方式,水可以在一個圓中流動。
輸入
輸入包括幾種情況。對於每一種情況,第一行包含兩個空間分離的整數,n(0<n<=200)和m(2 <=m <=200)。N是農民約翰挖溝的數量。M是那些溝渠的交叉點。十字路口1是池塘。交叉點M是流。以下n行中的每一個包含三個整數,SI、穎娃和CI。Si和Ei(1<Si,Ei <=m)表示該溝之間的交匯點。水將從這條溝從Si流入穎娃。CI(0<CI=10000000)是水通過溝道的最大速率。
輸出
對於每一種情況,輸出一個單一的整數,水可以從池塘中排空的最大速率。
樣本輸入
5,4,1,2,40,1,4,20,2,4,20,2,2,
樣本輸出
50
const int maxn = 210;
const int inf = 1 << 30;
struct edge {
int v, f, nxt;
}e[maxn << 1];
int num, n, m, s, t, g[maxn];
queue<int> que;
int vis[maxn], d[maxn];
void addedge(int u, int v, int val) {
e[++num].v = v;
e[num].f = val;
e[num].nxt = g[u];
g[u] = num;
e[++num].v = u;
e[num].f = 0;
e[num].nxt = g[v];
g[v] = num;
}
void bfs() {
memset(d, 0, sizeof(d));
while (!que.empty()) que.pop();
vis[s] = 1, que.push(s);
while (!que.empty()) {
int u = que.front(); que.pop();
for (int i = g[u]; i; i = e[i].nxt) {
if (e[i].f && !vis[e[i].v]) {
d[e[i].v] = d[u] + 1;
vis[e[i].v] = 1;
que.push(e[i].v);
}
}
}
}
int dfs(int u, int flow) {
if (u == t)
return flow;
else {
int ans = 0;
for (int i = g[u]; flow&&i; i = e[i].nxt) {
if (e[i].f&&d[e[i].v] == d[u] + 1) {
int dd = dfs(e[i].v, min(e[i].f, flow));
e[i].f -= dd;
e[i ^ 1].f += dd;
flow -= dd;
ans += dd;
}
}
return ans;
}
}
int dinic() {
int ans = 0;
while (true) {
memset(vis, 0, sizeof(vis));
bfs();
if (!vis[t])
return ans;
ans += dfs(s, inf);
}
}
int main() {
ios::sync_with_stdio(false);
while (cin >> m >> n) {
memset(g, 0, sizeof(g));
num = 1;
int x, y, z;
while (m--) {
cin >> x >> y >> z;
addedge(x, y, z);
}
s = 1, t = n;
cout << dinic() << endl;
}
return 0;
}