題目描述
如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。
輸入格式
第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。
接下來M行每行包含三個正整數ui、vi、wi,表示第i條有向邊從ui出發,到達vi,邊權爲wi(即該邊最大流量爲wi)
輸出格式
一行,包含一個正整數,即爲該網絡的最大流。
輸入輸出樣例
輸入 #1
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
輸出 #1
50
說明/提示
時空限制:1000ms,128M
數據規模:
對於30%的數據:N<=10,M<=25
對於70%的數據:N<=200,M<=1000
對於100%的數據:N<=10000,M<=100000
樣例說明:
題目中存在3條路徑:
4–>2–>3,該路線可通過20的流量
4–>3,可通過20的流量
4–>2–>1–>3,可通過10的流量(邊4–>2之前已經耗費了20的流量)
故流量總計20+20+10=50。輸出50。
實現代碼
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1e4;
const int maxm = 1e5;
const int Inf = 0x3f3f3f3f;
int n, m, cnt = 0;
int head[maxn], cur[maxn], deep[maxn];
struct Edge {
int to, nxt, cap;
}edge[maxm << 1];
void Link(int f, int t, int c) {
edge[cnt].cap = c, edge[cnt].to = t, edge[cnt].nxt = head[f], head[f] = cnt++;
}
inline bool bfs(int s, int t) {
for (int i = 0; i <= n; i++) cur[i] = head[i];
memset(deep, -1, sizeof(deep));
queue<int> q;
q.push(s);
deep[s] = 0;
while (q.size()) {
int f = q.front();
q.pop();
for (int i = head[f]; i != -1; i = edge[i].nxt) {
int to = edge[i].to, cap = edge[i].cap;
if (deep[to] == -1 && cap) {
deep[to] = deep[f] + 1;
if (to == t) return true;
q.push(to);
}
}
}
return false;
}
int dfs(int s, int t, int flow) {
if (s == t || flow == 0) return flow;
int toflow = 0, f;
for (int i = cur[s]; i != -1; i = edge[i].nxt) {
cur[s] = i;
int to = edge[i].to, cap = edge[i].cap;
if (deep[to] == deep[s] + 1 && (f = dfs(to, t, min(flow, cap)))) {
toflow += f;
flow -= f;
edge[i].cap -= f;
edge[i ^ 1].cap += f;
if (!flow) break;
}
}
return toflow;
}
void dinic(int s, int t) {
int maxflow = 0;
while (bfs(s, t)) {
maxflow += dfs(s, t, Inf);
}
cout << maxflow << endl;
}
int main() {
memset(head, -1, sizeof(head));
int u, v, w, s, t;
cin >> n >> m >> s >> t;
while (m--) {
cin >> u >> v >> w;
Link(u, v, w);
Link(v, u, 0);
}
dinic(s, t);
return 0;
}