首先来认识一下网络流中最大流的问题

给定一个有向图G=(V,E),把图中的边看做成管道,边权看做成每根管道能通过的最大流量(容量),给定源点s和汇点t,在源点有一个水源,在汇点有一个蓄水池,问s-t的最大水流量是多少

网络流图里,源点流出的量等于汇点流入的量,除源汇外的任何点,其流入量之和等于流出量之和 。

首先我们来看下面的图

网络流相关知识点以及题目//POJ1273 POJ 3436 POJ2112 POJ 1149

s是源点,t是汇点

先这么想,先用dfs找出一条从s-t的路线,把他塞满,然后流量就是路径中容量最小的那条路的容量,然后把路径上的容量都剪去这个流量,再重新从s-t找可行路径,直到找不到为止

用这种思路看这个图

先走S-A-B-T,这样流量为100,并且没有可行路径了,即操作结束.

可是很明显,从S-A-T,S-B-T这两条路加起来的流量为200。所以这种思路是错的。

主要是过早的认为A-B的流量不为0

改进的思路:建立一个可以修改的网络,使得不合理的流可以被删掉

一种实现:对上次dfs时找到的流量路径上的边,添加一条“反向”边,反向边上的容量等于上次dfs时找到的该边上的流量,然后再利用“反向”的容量和其他边上剩余的容量寻找路径。

使用这种思路再求一次

第一次dfs后

网络流相关知识点以及题目//POJ1273 POJ 3436 POJ2112 POJ 1149

第二次dfs(为了方便把容量为0的边删了)

网络流相关知识点以及题目//POJ1273 POJ 3436 POJ2112 POJ 1149

这个时候已经没有可以走的边了,流量为200,dfs结束

为什么这种思路是正确的呢,网上有不少详细的证明。

Ford-Fulkerson算法
就是用这种思路做的

用dfs求增广路径,每次找到之后处理,直到找不到为止。

假设有n个定点,m条边,那么dfs的复杂度为n+m;

dfs运行c次

所以复杂度为c*(n+m);

但是dfs可能会运行很多次。

比如上面的图如果A-B中有条容量为1的边,那么运气不好的话,能执行200次dfs;

但实际上只要用2次就能找到

在每次增广的时候,选择从源到汇的具有最少边数的增广路径,即不是通过dfs寻找增广路径,而是通过bfs寻找增广路径。
这就是Edmonds-Karp 最短增广路算法
已经证明这种算法的复杂度上限为nm2 (n是点数, m是边数);

现在来说几道题目

1-〉POJ 1273

题意:网络流的裸题,1为源点,n为汇点,给定每条边的容量,求最大流,用EK算法

1273 Accepted 1052K 0MS G++ 1430B
 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <stdlib.h>
 4 #include <string.h>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <queue>
 8 using namespace std;
 9 #define N 300
10 #define INF 0x7fffffff
11 int Map[N][N];
12 int path[N];
13 //bool vis[N];
14 int n,m;
15 bool bfs(int s,int t)
16 {
17     int p;
18     queue<int> q;
19     memset(path,-1,sizeof(path));
20    //memset(vis,false,sizeof(vis));
21     path[s]=s;
22    // vis[s]=true;
23     q.push(s);
24     while(!q.empty())
25     {
26         p=q.front();
27         q.pop();
28         for(int i=1;i<=n;i++)
29         {
30             if(Map[p][i]>0&&path[i]==-1)
31             {
32                 path[i]=p;
33                 //vis[i]=true;
34                 if(i==t)
35                     return true;
36                 q.push(i);
37             }
38         }
39     }
40     return false;
41 }
42 int EK(int s,int t)
43 {
44     int flow=0;
45     int d;
46     int i;
47     while(bfs(s,t))
48     {
49         d=INF;
50         for(i=t;i!=s;i=path[i])
51         {
52             d=min(d,Map[path[i]][i]);
53         }
54         for(i=t;i!=s;i=path[i])
55         {
56             Map[path[i]][i]-=d;
57             Map[i][path[i]]+=d;
58         }
59         flow+=d;
60     }
61     return flow;
62 }
63 int main()
64 {
65     while(scanf("%d %d",&m,&n)!=EOF)
66     {
67         memset(Map,0,sizeof(Map));
68         for(int i=1;i<=m;i++)
69         {
70             int from,to,flow;
71             scanf("%d %d %d",&from,&to,&flow);
72             Map[from][to]+=flow;
73         }
74         printf("%d\n",EK(1,n));
75     }
76     
77     return 0;
78 }
View Code

相关文章:

  • 2022-01-18
  • 2022-12-23
  • 2021-07-20
  • 2022-03-07
  • 2022-12-23
  • 2021-12-23
  • 2021-05-25
  • 2021-12-07
猜你喜欢
  • 2021-06-13
  • 2022-12-23
  • 2022-12-23
  • 2022-01-04
  • 2022-12-23
  • 2021-05-27
  • 2021-07-05
相关资源
相似解决方案