链接:点击跳转
在开始建边的时候同时建一条反向边,然后在减少边权的时候给反边加上边权,每一次寻找从s到t的独立路径,记录前驱和该路径所在的数组下标,更新所能到达该点的流量(为该路径的边权和前驱的流量中的较小值),直到到达t点,返回t点得到的流量,如果到达不了t点,即不存在增广路,则算法结束,如果有增广路,将流量加入结果,将该路径上每一个边都删除该流量值,反边则加上流量值
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll MAXN = 1e5 + 5e2;
const int INF = 0x3f3f3f3f;
#define endl '\n'
inline void IO_STREAM() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
struct Edge{
int to,val,nxt;
}e[MAXN];
int head[MAXN], pre[MAXN], rec[MAXN], flow[MAXN];
int n, m, s, t, cnt;
ll res;
inline void init() {
memset(head, -1, sizeof(head));
cnt = 0;
}
inline void add(int from, int to, int val) {
e[cnt] = Edge{to, val, head[from]};
head[from] = cnt++;
}
inline int dfs() {
memset(pre, -1, sizeof(pre));
pre[s] = s;flow[s] = INF;
stack<int>q;
q.push(s);
while (!q.empty()) {
int now = q.top();
q.pop();
for (int i = head[now]; i != -1; i = e[i].nxt) {
if (pre[e[i].to] == -1 && e[i].val > 0) {
flow[e[i].to] = min(flow[now], e[i].val);
pre[e[i].to] = now;
rec[e[i].to] = i;
q.push(e[i].to);
}
}
if (pre[t] != -1) return flow[t];
}
return -1;
}
inline void ff() {
int add;
while ((add = dfs()) != -1) {
res += add;
int k = t;
while (k != s) {
e[rec[k]].val -= add;
e[(rec[k] ^ 1)].val += add;
k = pre[k];
}
}
}
int main() {
IO_STREAM();
while (cin >> n >> m >> s >> t) {
init();
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
add(v, u, 0);
}
res = 0;
ff();
cout << res << endl;
}
return 0;
}