网络流之最大流-Ford-Fullkerson算法 DFS && BFS
Posted shuaihui520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流之最大流-Ford-Fullkerson算法 DFS && BFS相关的知识,希望对你有一定的参考价值。
DFS
#include <iostream> #include <stdio.h> #include <vector> #include <algorithm> #include <cstring> using namespace std; const int max_v = 1000; const int INF = 0x3f3f3f3f; struct edge { int to,cap,rev; //rev是反向边的编号,即这条反向边是以to为起点的第几条边 }; vector<edge> G[max_v]; bool used[max_v]; void add(int from,int to,int cap) { G[from].push_back((edge){to,cap,G[to].size()});//因为下一步要加一条反向边,所以不需要-1 G[to].push_back((edge){from,0,G[from].size()-1}); } int dfs(int v,int t,int f) { if(v==t) return f; used[v]=1; for(int i =0;i<G[v].size();++i) { edge &e = G[v][i]; if(!used[e.to] && e.cap > 0) { int d = dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d;//给上一层的d,让上一层也能更新; } } } return 0; } int main() { int m,s,t; scanf("%d%d%d",&s,&t,&m); int from,to,cap; for(int i=0;i<m;++i) { //点从1号开始。 scanf("%d%d%d",&from,&to,&cap); add(from,to,cap); } int flow=0; while(1) { memset(used,0,sizeof(used)); int f=dfs(s,t,INF); if(f==0) break; flow+=f; } printf("%d",flow); return 0; } /* 1 4 7 1 2 10 1 5 2 2 5 6 2 3 6 3 4 8 3 5 3 5 4 5 结果:11 */
BFS(优化)
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; const int maxn = 1000001; const int INF = 0x3f3f3f; struct no { int to; int cap; int rev; }; vector<no> G[maxn]; int level[maxn];///顶点到源点的距离标记 int iter[maxn];///当前弧,在其之前的边没有用了 void add(int from,int to,int cap) { G[from].push_back((no){to,cap,G[to].size()}); G[to].push_back((no){from,0,G[from].size()-1}); } void bfs(int s) { memset(level,-1,sizeof(level)); queue<int> que; level[s] = 0; que.push(s); while(!que.empty()) { int v = que.front( ) ; que.pop( ); for(int i=0 ; i<G[v].size( ) ; i++) { no &e = G[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to] = level[v]+1; que.push(e.to); } } } } int dfs(int v,int t, int f) { if(v==t) return f; for(int &i=iter[v];i<G[v].size();++i)//这里是引用,i++的同时iter也++,其实相当于上个的used,不过不用判断了 { no &e = G[v][i]; if(e.cap>0 && level[e.to]>level[v]) { int d=dfs(e.to,t,min(e.cap,f)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int max_flow(int s,int t) { int flow = 0; for( ; ; ) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,INF))>0) flow+=f; } } int main() { int s,t,m,n; scanf("%d%d%d%d",&n,&m,&s,&t); int u,v,cap; for(int i=0;i<m;++i) { scanf("%d%d%d",&u,&v,&cap); add(u,v,cap); } printf("%d",max_flow(s,t)); return 0; }
神奇代码:巨快
#include <bits/stdc++.h> const int MAXN = 1e6 + 10; const int INF = 0x3f3f3f3f; struct Node { int v, f, index; Node(int v, int f, int index) : v(v), f(f), index(index) {} }; int n, m, s, t; std::vector<Node> edge[MAXN]; std::vector<int> list[MAXN], height, count, que, excess; typedef std::list<int> List; std::vector<List::iterator> iter; List dlist[MAXN]; int highest, highestActive; typedef std::vector<Node>::iterator Iterator; void init() { for(int i=0; i<=n; i++) edge[i].clear(); } void addEdge(const int u, const int v, const int f) { edge[u].push_back(Node(v, f, edge[v].size())); edge[v].push_back(Node(u, 0, edge[u].size() - 1)); } void globalRelabel(int n, int t) { height.assign(n, n); height[t] = 0; count.assign(n, 0); que.clear(); que.resize(n + 1); int qh = 0, qt = 0; for (que[qt++] = t; qh < qt;) { int u = que[qh++], h = height[u] + 1; for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) { if (height[p->v] == n && edge[p->v][p->index].f > 0) { count[height[p->v] = h]++; que[qt++] = p->v; } } } for (int i = 0; i <= n; i++) { list[i].clear(); dlist[i].clear(); } for (int u = 0; u < n; ++u) { if (height[u] < n) { iter[u] = dlist[height[u]].insert(dlist[height[u]].begin(), u); if (excess[u] > 0) list[height[u]].push_back(u); } } highest = (highestActive = height[que[qt - 1]]); } void push(int u, Node &e) { int v = e.v; int df = std::min(excess[u], e.f); e.f -= df; edge[v][e.index].f += df; excess[u] -= df; excess[v] += df; if (0 < excess[v] && excess[v] <= df) list[height[v]].push_back(v); } void discharge(int n, int u) { int nh = n; for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) { if (p->f > 0) { if (height[u] == height[p->v] + 1) { push(u, *p); if (excess[u] == 0) return; } else { nh = std::min(nh, height[p->v] + 1); } } } int h = height[u]; if (count[h] == 1) { for (int i = h; i <= highest; i++) { for (List::iterator it = dlist[i].begin(); it != dlist[i].end(); ++it) { count[height[*it]]--; height[*it] = n; } dlist[i].clear(); } highest = h - 1; } else { count[h]--; iter[u] = dlist[h].erase(iter[u]); height[u] = nh; if (nh == n) return; count[nh]++; iter[u] = dlist[nh].insert(dlist[nh].begin(), u); highest = std::max(highest, highestActive = nh); list[nh].push_back(u); } } int hlpp(int n, int s, int t) { if (s == t) return 0; highestActive = 0; highest = 0; height.assign(n, 0); height[s] = n; iter.resize(n); for (int i = 0; i < n; i++) if (i != s) iter[i] = dlist[height[i]].insert(dlist[height[i]].begin(), i); count.assign(n, 0); count[0] = n - 1; excess.assign(n, 0); excess[s] = INF; excess[t] = -INF; for (int i = 0; i < (int)edge[s].size(); i++) push(s, edge[s][i]); globalRelabel(n, t); for (int u /*, res = n*/; highestActive >= 0;) { if (list[highestActive].empty()) { highestActive--; continue; } u = list[highestActive].back(); list[highestActive].pop_back(); discharge(n, u); // if (--res == 0) globalRelabel(res = n, t); } return excess[t] + INF; } int main() { while(~scanf("%d %d %d %d", &n, &m, &s, &t)){ init(); for (int i = 0, u, v, f; i < m; i++) { scanf("%d %d %d", &u, &v, &f); addEdge(u, v, f); } printf("%d", hlpp(n + 1, s, t));///点是1~n范围的话,貌似要 n+1 } return 0; }
以上是关于网络流之最大流-Ford-Fullkerson算法 DFS && BFS的主要内容,如果未能解决你的问题,请参考以下文章