Drainage Ditches(最大流)
思路:最大流的裸題,此題數據較小,用算法較方便。
第一次寫記錄一下算法的實現:
增廣路徑:從源點(類似起點)到匯點(類似終點) 的一條可行流的路徑。
1.尋找增廣路徑並記錄增廣路徑,找到在該路徑上的最大流。
2.加上該貢獻,然後對其路徑建立反路徑, (保證有反悔性質的貪心,得到最優解。)
3.直到找不到增廣路徑推出循環,返回總貢獻值。
時間複雜度:,分別爲結點數,邊數。
複雜度證明:因爲一次,需要的複雜度,總共需要次。
所以時間複雜度爲:
#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;
}