[网络最大流模板题](https://www.luogu.com.cn/problem/P3376).

网络流的相关定义:

源点:有n个点,有m条有向边,有一个点很特殊,只出不进,叫做源点。
汇点:另一个点也很特殊,只进不出,叫做汇点。
容量和流量:每条有向边上有两个量,容量和流量,从i到j的容量通常用c[i,j]表示,流量则通常是f[i,j].
通常可以把这些边想象成道路,流量就是这条道路的车流量,容量就是道路可承受的最大的车流量。很显然的,流量<=容量。而对于每个不是源点和汇点的点来说,可以类比的想象成没有存储功能的货物的中转站,所有“进入”他们的流量和等于所有从他本身“出去”的流量。

最大流:把源点比作工厂的话,问题就是求从工厂最大可以发出多少货物,是不至于超过道路的容量限制,也就是,最大流。

思想:起初最大流ans=0,每次找一条从汇到源的路,找到这条路的最小的流量minn,累加到最大流ans,这条路的每一段流量减去minn,同时反向边加上minn。
参考文章.
参考.

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,s,t;
ll mp[205][205]={{0}};    //两点之间流量
int father[205]={0};	//用于遍历一条路
int vis[205]={0};		//标记
ll ans = 0;				//最大流
ll minn[205];			//一条路最小的流量
vector<int> e[205];		//邻接矩阵
int bfs(){	
	memset(vis,0,sizeof(vis));
	queue<int> q;
	q.push(s);
	vis[s]=1;
	minn[s] = 1e9;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int i = 0; i < e[u].size(); i++){
			int v = e[u][i];
			if(mp[u][v]==0 || vis[v]) continue;
			minn[v]=min(minn[u],mp[u][v]);	//源到v最小流量=min(源到u,u到v)
			father[v]=u;  
			vis[v]=1;
			q.push(v);
			if(v==t) return 1;   		//存在从源到汇 true
		}
	}
	return 0;					//不存在 false
}
void update(){
	int u = t;
	while(u!=s){
		int v = father[u];
		mp[u][v]+=minn[t];		//反向边加
		mp[v][u]-=minn[t];		//正向边减
		u=v;
	}
	ans+=minn[t];
}
int main(){
	cin>>n>>m>>s>>t;
	int flag[205][205]={{0}};		//处理重边
	while(m--){
		int u,v,w;
		cin>>u>>v>>w;
		if(flag[u][v]==0){
			e[u].push_back(v);	
			e[v].push_back(u);
		}
		mp[u][v]+=w;		//处理重边
	}	
	while(bfs()) update();
	cout<<ans<<endl;

	return 0;
} 

猜你喜欢

转载自blog.csdn.net/HHeyanjie/article/details/107402530