原题地址:https://www.luogu.org/problemnew/show/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 <iostream>
#include <vector>
#include <cstring>
#include <queue>
#include <cstdio>
#define INF 0x3f3f3f3f
using namespace std;
struct Line{
int r, w;
Line() = default;
Line(int r, int w): r(r), w(w){ }
}line[200005];
vector<int> g[10005];
int deep[10005];
int n, m, s, t;
bool bfs()
{
memset(deep, 0, sizeof(deep));
queue<int> que;
que.push(s);
deep[s] = 1;
while(!que.empty()){
int top = que.front();
que.pop();
for(int i = 0; i < g[top].size(); i ++){
int z = g[top][i];
if(!deep[line[z].r] && line[z].w){ //通过非饱和弧记录深度
que.push(line[z].r);
deep[line[z].r] = deep[top] + 1;
if(deep[t])
return true;
}
}
}
return false;
}
int dfs(int x, int mix) //mix为当前流量
{
//cout << x << " " << mix << endl;
if(!mix || x == t){
return mix;
}
int ap = 0; //从点x最多流出量
for(int i = 0; i < g[x].size(); i ++){
int z = g[x][i];
if(deep[line[z].r] > deep[x] && line[z].w){
int p = dfs(line[z].r, min(mix, line[z].w));
ap += p;
mix -= p; //p流走了
line[z].w -= p;
line[z^1].w += p;
if(!mix){
return ap;
}
}
}
return ap;
}
int dinic()
{
int ans = 0;
while(bfs()){
ans += dfs(s, INF);
}
return ans;
}
int main()
{
while(cin >> n >> m >> s >> t){
for(int i = 0; i < m; i ++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
//cin >> u >> v >> w;
line[i * 2] = Line(v, w);
line[i * 2 + 1] = Line(u, 0);
g[u].push_back(i * 2);
g[v].push_back(i * 2 + 1);
}
printf("%d\n", dinic());
//cout << dinic() << endl;
for(int i = 1; i <= n; i ++)
g[i].clear();
}
return 0;
}