[关闭]
@zhangche0526 2017-02-25T06:36:14.000000Z 字数 1378 阅读 869

网络流

最大流

描述

在图中,给出每条边的最大流,求出从一给定源点到汇点的最大流

算法

单纯的贪心法由于搜索顺序会导致结果不同的问题并不能保证求出正确的答案,只需要将原始贪心算法中加入一个“反悔”机制就可以保证求出正确答案

实现中只需要加入反向边,没流过一条边,就将这条边的边权减去流量,并把反向边的边权加上这个流量

实际上就是通过加入反向边实现抵消操作

Ford-Fulkerson

dfs

时间复杂度:

Edmonds-Karp

bfs优化

时间复杂度:

Dinic

每次找一条路前,先通过一次bfs更新每个点的level,目的是在之后的dfs中优先遍历深度浅的点

加入当前弧优化,避免对一条没有用的便进行多次检查

时间复杂度:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<queue>
  4. using namespace std;
  5. const int MAXV=100,INF=1e9;
  6. struct E{int to,cap,rev;};
  7. vector<E> G[MAXV];
  8. int level[MAXV];
  9. int iter[MAXV];//当前弧,在其之前的边已经没有用了
  10. void addEdge(int u,int v,int c)
  11. {
  12. G[from].push_back((E){u,c,G[to].size()});
  13. G[to].push_back((E){v,0,G[from].size()-1});
  14. }
  15. void bfs(int s)
  16. {
  17. memset(level,-1,sizeof(level));
  18. queue<int> que;
  19. level[s]=0;
  20. que.push(s);
  21. while(!que.empty())
  22. {
  23. int u=que.front();que.pop();
  24. for(int v=0;v<G[u].size();v++)
  25. {
  26. E & e=G[u][i];
  27. if(e.cap>0&&level[e.to]<0)
  28. {
  29. level[e.to]=level[u]+1;
  30. que.push(e.to);
  31. }
  32. }
  33. }
  34. }
  35. int dfs(int v,int t,int f)
  36. {
  37. if(v==t) return f;
  38. for(int & i=iter[v];i<G[v].size();i++)//当前弧优化
  39. {
  40. E & e=G[v][i];
  41. if(e.cap>0&&level[v]<level[e.to])
  42. {
  43. int d=dfs(e.to,t,min(f,e.cap));
  44. if(d>0)
  45. {
  46. e.cap-=d;
  47. G[e.to][e.rev].cap+=d;
  48. return d;
  49. }
  50. }
  51. }
  52. }
  53. int maxFlow(int s,int t)
  54. {
  55. int flow=0;
  56. while(true)
  57. {
  58. bfs(s);
  59. if(level[t]<0) return flow;//若bfs搜不到汇点,返回值即可
  60. memset(iter,0,sizeof(iter));
  61. int f;
  62. while((f=dfs(s,t,INF))>0)
  63. flow+=f;
  64. }
  65. }

最小割

最大流=最小割

最大流的变体

多个源点和汇点

增加一个超级源点s和一个超级汇点t,从s向每个源点加入一条容量无穷的边,从每一个汇点向t加入一条容量无穷的边

无向图

加两条边即可

顶点上流量限制

把结点“割开”,所有入边连到一点A上,所有出边连到一点B上,从A向B连一条cap为该结点流量限制的边即可

最大流的应用

二分图匹配

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注