题目地址:
https://www.acwing.com/problem/content/2174/
给定一个包含 n n n个点 m m m条边的有向图,并给定每条边的容量,边的容量非负。图中可能存在重边和自环。求从点 S S S到点 T T T的最大流。
输入格式:
第一行包含四个整数
n
,
m
,
S
,
T
n,m,S,T
n,m,S,T。接下来
m
m
m行,每行三个整数
u
,
v
,
c
u,v,c
u,v,c,表示从点
u
u
u到点
v
v
v存在一条有向边,容量为
c
c
c。点的编号从
1
1
1到
n
n
n。
输出格式:
输出点
S
S
S到点
T
T
T的最大流。如果从点
S
S
S无法到达点
T
T
T则输出
0
0
0。
数据范围:
2
≤
n
≤
10000
2≤n≤10000
2≤n≤10000
1
≤
m
≤
100000
1≤m≤100000
1≤m≤100000
0
≤
c
≤
10000
0≤c≤10000
0≤c≤10000
S
≠
T
S≠T
S=T
#include <iostream>
#include <cstring>
using namespace std;
const int N = 10010, M = 200010, INF = 1e8;
int n, m, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N];
void add(int a, int b, int c) {
e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx++;
e[idx] = a, ne[idx] = h[b], f[idx] = 0, h[b] = idx++;
}
bool bfs() {
int hh = 0, tt = 0;
memset(d, -1, sizeof d);
q[tt++] = S, d[S] = 0, cur[S] = h[S];
while (hh < tt) {
int t = q[hh++];
for (int i = h[t]; ~i; i = ne[i]) {
int v = e[i];
if (d[v] == -1 && f[i]) {
d[v] = d[t] + 1;
cur[v] = h[v];
if (v == T) return true;
q[tt++] = v;
}
}
}
return false;
}
int find(int u, int limit) {
if (u == T) return limit;
int flow = 0;
for (int i = cur[u]; ~i && flow < limit; i = ne[i]) {
cur[u] = i;
int v = e[i];
if (d[v] == d[u] + 1 && f[i]) {
int t = find(v, min(f[i], limit - flow));
if (!t) d[v] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
int dinic() {
int r = 0, flow;
while (bfs()) while (flow = find(S, INF)) r += flow;
return r;
}
int main() {
scanf("%d%d%d%d", &n, &m, &S, &T);
memset(h, -1, sizeof h);
while (m--) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
printf("%d\n", dinic());
return 0;
}