最大流dinic算法
因为一个min写错又调了半个小时 —— 《一名OIer的血泪史》
洛谷 P3376 网络最大流
题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:
第一行包含四个正整数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
代码
#include<cstdio>
#include<cstring>
using namespace std;
const int inf = 0x3f3f3f;
int n, m, s, t, tot = -1, ans = 0;
int st[200001], dep[10001];
int min(int a, int b) { return a < b ? a : b; }
struct node
{
int to, val, last;
}c[200001];
void add(int u, int v, int w)
{
c[++tot].to = v;
c[tot].val = w;
c[tot].last = st[u];
st[u] = tot;
}
bool bfs()
{
int q[10001], l = 0, r = 1;
memset(dep, 0, sizeof dep);
dep[s] = 1;
q[r] = s;
while (l != r)
{
int head = q[++l];
for (int i = st[head]; i != -1; i = c[i].last)
{
if (c[i].val > 0 && !dep[c[i].to])
{
dep[c[i].to] = dep[head] + 1;
q[++r] = c[i].to;
}
}
}
if (!dep[t])
return false;
return true;
}
int dfs(int u, int k)
{
if (u == t) return k;
for (int i = st[u]; i != -1; i = c[i].last)
{
if ((dep[c[i].to] == dep[u] + 1) && c[i].val)
{
int p = dfs(c[i].to, min(c[i].val, k));
if (p > 0)
{
c[i].val -= p;
c[i ^ 1].val += p;
return p;
}
}
}
return 0;
}
void dinic()
{
while (bfs())
while (int p = dfs(s, inf))
ans += p;
return;
}
int main()
{
memset(st, -1, sizeof st);
scanf("%d%d%d%d", &n, &m, &s, &t);
for (int i = 0; i < m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, 0);
}
dinic();
printf("%d\n", ans);
return 0;
}