[ネットワーク最大ストリームテンプレートの問題](https://www.luogu.com.cn/problem/P3376).

13950 ワード

ネットワーク・フローに関する定義:
ソースポイント:n個のポイントがあり、m個のエッジがあり、1つのポイントが特殊で、出られないだけで、ソースポイントと呼ばれています.汇点:もう一つの点も特殊で、入れないだけで、汇点と呼ばれています.容量と流量:各有向辺に2つの量、容量と流量があり、iからjまでの容量は通常c[i,j]で表され、流量は通常f[i,j]である.通常はこれらの辺を道路と想像することができて、流量はこの道路の車の流量で、容量は道路が耐えられる最大の車の流量です.明らかに,流量<=容量である.ソースポイントと送金ポイントではないポイントごとに、記憶機能のない貨物の中継所を類比することができ、すべての「入る」彼らの流量と、彼自身から「出る」すべての流量に等しい.
最大流:源点を工場にたとえると、問題は工場から最大でどれだけの貨物を出すことができるかを求め、道路の容量制限を超えない、つまり、最大流である.
思想:最初は最大流ans=0で、毎回1本の源に集まる道を探して、この道の最小の流量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){
			flag[u][v] = 1;
			e[u].push_back(v);	
			e[v].push_back(u);
		}
		mp[u][v]+=w;		//    
	}	
	while(bfs()) update();
	cout<<ans<<endl;

	return 0;
}