洛谷P3376 【模板】网络最大流

时间:2019-02-15
本文章向大家介绍洛谷P3376 【模板】网络最大流,主要包括洛谷P3376 【模板】网络最大流使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

原题地址: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(!line[z].w){     //回溯到第一个line[z].w为0的边的出发点 
				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;
}