题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:
第一行包含四个正整数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 <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int inf = 0x7fffffff;
const int mn = 1e4 + 10, mm = 1e5 + 10;
int edge;
int fr[mn];
int cur[2 * mn]; /// 当前弧优化
int lv[4 * mn];
struct node
{
int to, val, nx, fan;
} e[2 * mm];
void addedge(int u, int v, int w)
{
edge++;
e[edge].to = v, e[edge].val = w, e[edge].nx = fr[u], e[edge].fan = edge + 1;
fr[u] = edge;
edge++;
e[edge].to = u, e[edge].val = 0, e[edge].nx = fr[v], e[edge].fan = edge - 1;
fr[v] = edge;
}
void bfs(int s)
{
memset(lv, 0, sizeof lv);
lv[s] = 1;
queue<int> q;
q.push(s);
while (!q.empty())
{
int t = q.front();
q.pop();
for (int i = fr[t]; i != -1; i = e[i].nx)
{
if (e[i].val > 0 && !lv[e[i].to])
{
lv[e[i].to] = lv[t] + 1;
q.push(e[i].to);
}
}
}
}
int dfs(int s, int t, int f)
{
if (s == t)
return f;
for (int &i = cur[s]; i != -1; i = e[i].nx)
{
if (e[i].val > 0 && lv[s] < lv[e[i].to])
{
int d = dfs(e[i].to, t, min(f, e[i].val));
if (d > 0)
{
e[i].val -= d;
e[e[i].fan].val += d;
return d;
}
}
}
return 0;
}
int main()
{
freopen("D:\\in.txt", "r", stdin);
memset(fr, -1, sizeof fr);
int n, m, s, t;
scanf("%d %d %d %d", &n, &m, &s, &t);
while (m--)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
addedge(u, v, w);
}
int flow = 0;
while (1)
{
bfs(s);
if (!lv[t])
break;
for (int i = 1; i <= n; i++)
cur[i] = fr[i];
int f = 0;
while ((f = dfs(s, t, inf)) > 0)
flow += f;
}
printf("%d\n", flow);
return 0;
}