Drainage Ditches(最大流)

Drainage Ditches(最大流)

傳送門

思路:最大流的裸題,此題數據較小,用EdmondsKarpEdmonds-Karp算法較方便。


第一次寫記錄一下算法的實現:

增廣路徑:從源點(類似起點)到匯點(類似終點) 的一條可行流的路徑。

1.尋找增廣路徑並記錄增廣路徑,找到在該路徑上的最大流。

2.加上該貢獻,然後對其路徑建立反路徑, (保證有反悔性質的貪心,得到最優解。)

3.直到找不到增廣路徑推出循環,返回總貢獻值。


時間複雜度:O(nm2)O(nm^2),n,mn,m分別爲結點數,邊數。

複雜度證明:因爲bfsbfs一次,需要O(m)O(m)的複雜度,總共需要bfs O(nm)bfs\ O(nm)次。

所以時間複雜度爲:O(nm2)O(nm^2)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=205,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
int n,m,st,ed,pre[N],g[N][N];	//pre[i] 記錄路徑. 
int bfs(){	//求增廣路的最大流速. 
	int flow[N];	//保存流速. 
	mst(pre);
	queue<int>q;
	q.push(st);
	flow[st]=inf;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=1;i<=n;i++){
			if(i!=st&&g[u][i]&&!pre[i]){
				pre[i]=u;
				q.push(i);
				flow[i]=min(flow[u],g[u][i]);
			}
		}
	}
	return pre[ed]?flow[ed]:-1;
}
int EK_flow(){
	int ans=0;
	while(1){
		int flow=bfs();
		if(flow==-1) break;//沒有增廣路說明當前已經是最大流. 
		int now=ed;
		while(now!=st){
			int fa=pre[now];
			g[fa][now]-=flow;
			g[now][fa]+=flow;	//重點:對殘留網絡建立反向路徑 
			now=fa;
		}
		ans+=flow;
	}
	return ans;
}
int main(){
	while(~scanf("%d%d",&m,&n)){
		mst(g);
	for(int i=1;i<=m;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		g[u][v]+=w;	//重邊要將流速疊加起來 
	}
	st=1,ed=n;
	printf("%d\n",EK_flow());
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章