POJ1273 最大流模板題 初學網路流~
阿新 • • 發佈:2019-02-14
題意 不細說了,就是源是1,匯點是m的最大流模板
思路 初學網路流,拿這題練練手。
總結下EdmondsKarp演算法幾個要注意的點:
(1)演算法本質就是利用BFS不停地找增廣路,直到找不到為止。
(2)每次BFS後更新增廣路時,一定注意減去或加上的都是最後Terminal得到流量。
(3)用連線表存的時候,為了把平行邊存在相鄰位置上,可能會增加平行邊,為了避免這一點,可以在輸入的時候做些處理,不過對最大流來說感覺不處理也不會有什麼太大問題。當然用鄰接矩陣來存就好辦了,對平行邊累加流量就好了。
對這題來說,就是注意輸入是多組的.....還有有平行邊的存在
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <cstring> using namespace std; #define maxn 205 #define maxm 500 const int inf = 0x3f3f3f3f; struct Edge{ int fr,to,val; int next; Edge(int fr=0,int to=0,int val=0,int next=-1):fr(fr),to(to),val(val),next(next){ } void set(int f=0,int t=0,int v=0,int n=-1) { fr = f; to = t; val = v; next = n; } }edge[maxm]; int g[maxn]; int n,m; void addEdge(){ int f,t,v,i,j; int now = 0; memset(g,-1,sizeof(g)); for(i=0;i<m;i++) { scanf("%d%d%d",&f,&t,&v); edge[now].set(f,t,v,g[f]); g[f] = now++; //這裡這樣處理會造成重邊 edge[now].set(t,f,0,g[t]); g[t] = now++; } } int flow[maxn]; int path[maxn]; int bfs(int st,int ter) { memset(path,-1,sizeof(path)); flow[st] = inf; queue<int> q; q.push(st); while(q.size()!=0 && path[ter] ==-1) { int now = q.front(); q.pop(); for(int e = g[now];e != -1;e=edge[e].next) { //若這點被訪問過或者這條邊殘量為0則跳過 if(path[edge[e].to]!=-1 || edge[e].val==0 || edge[e].to == st) continue; flow[edge[e].to] = min(flow[now],edge[e].val); path[edge[e].to] = e; q.push(edge[e].to); } } while(q.size()) q.pop(); if(path[ter] == -1) return -1; return flow[ter]; } int EdmondsKarp(int st,int ter) { int sum = 0; path[st] = -1; while(bfs(st,ter)>=0) { sum += flow[ter]; //構建新的殘量圖 for(int e=path[ter];e!=-1;e=path[edge[e].fr]) { edge[e].val -= flow[ter]; edge[e^1].val += flow[ter]; } } return sum; } int main() { while(scanf("%d%d",&m,&n)==2) { addEdge(); cout<<EdmondsKarp(1,n)<<endl; } return 0; }
鄰接矩陣實現
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; const int maxn = 900; const int maxm = 10000; const int inf = 0x3f3f3f3f; struct EdmondsKarp{ //用到外部變數maxn,maxm,具體使用不非得按照模板 int n,m; int g[maxn][maxn]; int flow[maxn]; int path[maxn]; queue<int> q; void init(int nn=0) { n = nn; memset(g,0,sizeof(g)); memset(flow,0,sizeof(flow)); memset(path,-1,sizeof(path)); } void addOne(int u,int v,int yuan) { g[u][v] += yuan; m += 2; } int bfs(int s,int t) { int i; memset(path,-1,sizeof(path)); flow[s] = inf; //如果不加這句話,bfs內部就要一共三個判斷 path[s] = s; q.push(s); while(q.size()>0) { int tmp = q.front(); q.pop(); //這裡i從0開始還是1開始,視情況而定 for(i=0;i<n;i++) { if(g[tmp][i]>0 && path[i]==-1) { flow[i] = min(g[tmp][i],flow[tmp]); path[i] = tmp; q.push(i); if(i==t) { break; } } } if(path[t] != -1) break; } while(q.size()>0) q.pop(); if(path[t] == -1) return 0; else return flow[t]; } int go(int s,int t) { int ret = 0; while(bfs(s,t)) { int now = path[t]; int pre = t; ret += flow[t]; while(pre != s) { g[now][pre] -= flow[t]; g[pre][now] += flow[t]; pre = now; now = path[now]; } } return ret; } }edk; int main() { int n,m; while(scanf("%d%d",&m,&n) == 2) { edk.init(n); for(int i=0;i<m;i++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); edk.addOne(u-1,v-1,c); } cout<<edk.go(0,n-1)<<endl; } }