Edmonds-Karp算法求解最大流(POJ 1273)

题目POJ 1273  Drainage Ditches 

分析:经典的最大流问题,这里我们采用Edmonds-Karp算法(复杂度为$O(m^{2}n)$). 核心操作为BFS以及残差网络$G_{f}$的更新。对于BFS,为了得到$O(m)$的复杂度,采用邻接表。为了得到augmenting path之后更新$G_{f}$更加高效,我们为每条边编号。每条边$(u,v)$包括到达的结点$v$, 容量$cap$, 以及与该条边有同起点的边的编号。例如:从$u$出发有三条边$(u,v_{1})$, $(u,v_{2})$, $(u,v_{3})$, 三条边对应的编号分别为$t_{1}, t_{2}, t_{3}$, 令

$nex[t_{1}]=head[u]$;

$head[u]=t_{1}$;

$nex[t_{2}]=head[u]$;

$head[u]=t_{2}$;

$nex[t_{3}]=head[u]$;

$head[u]=t_{3}$;

我们可以得到

$nex[t_{1}]=head[u]$;

$nex[t_{2}]=t_{1}$;

$nex[t_{3}]=t_{2}$;

$head[u]=t_{3}$;

然后从$head[u]$我们可以得到$u$出发的边$t_{3}$, 然后通过$nex$可以得到$t_{2}$, $t_{1}$. 每条原始边的编号$i$为偶数(从$0$开始),对应的逆向边为$i$$^$$1$, 也即是$i+1$, 这样做的目的是在原始边和逆向边之间切换比较方便,$i$$^$$1=i+1$, $(i+1)$$^$$1=i$. 

代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<queue>
 4 #include<string.h>
 5 using namespace std;
 6 int utoe[205];//结点u对应的边e的编号
 7 int pres[205];
 8 int vist[205];//在BFS中判断每个结点是否被访问过
 9 int minc[205];
10 int s, t, maxflow;
11 int INF = 0x3f3f3f3f;
12 struct
13 {
14     int cap;//边的容量
15     int toVer;//边(u,v)对应的v
16     int nex;//边(u,v1)上一条共起点的边(u,v2)的编号
17 } edge[405];
18 bool BFS()
19 {
20     int e_idx;
21     int top_ele;
22     int v;
23     queue<int>q;//STL不支持清空队列,所以每次BFS都定义一个新的队列
24     memset(vist, 0, sizeof(vist));//标记每个结点是否被访问: 0表示没有,1表示有
25     q.push(s);
26     vist[s] = 1;
27     minc[s] = INF;
28     while (!q.empty())
29     {
30         top_ele = q.front();
31         q.pop();
32         e_idx = utoe[top_ele];
33         while (e_idx >= 0)
34         {
35             if (edge[e_idx].cap > 0)
36             {
37                 v = edge[e_idx].toVer;
38                 if (vist[v])
39                 {
40                     e_idx = edge[e_idx].nex;
41                     continue;
42                 }
43                 vist[v] = 1;
44                 minc[v] = min(minc[top_ele],edge[e_idx].cap);
45                 q.push(v);
46                 pres[v] = e_idx;
47                 if (v == t)
48                     return true;
49             }
50             e_idx = edge[e_idx].nex;
51         }
52     }
53     return false;
54 }
55 void Update()
56 {
57     int v = t;
58     int u;
59     while (v != s)
60     {
61         u = pres[v];
62         edge[u].cap -= minc[t];
63         edge[u^1].cap += minc[t];
64         v = edge[u^1].toVer;
65     }
66     maxflow += minc[t];
67 }
68 int main()
69 {
70     int m, n;
71     int u, v, c;
72     int i;
73     int id_e;
74     while (scanf("%d%d", &m, &n) == 2)
75     {
76         id_e = -1;
77         s = 1;
78         t = n;
79         memset(utoe, -1, sizeof(utoe));
80         for (i = 1; i <= m; i++)
81         {
82             scanf("%d%d%d", &u, &v, &c);
83             edge[++id_e].cap = c;
84             edge[id_e].toVer = v;
85             edge[id_e].nex = utoe[u];
86             utoe[u] = id_e;
87 
88             edge[++id_e].cap = 0;
89             edge[id_e].toVer = u;
90             edge[id_e].nex = utoe[v];
91             utoe[v] = id_e;
92         }
93         maxflow = 0;
94         while (BFS())
95             Update();
96         printf("%d\n", maxflow);
97     }
98     return 0;
99 }
View Code

posted on 2020-10-26 15:56  小叶子曰  阅读(87)  评论(0编辑  收藏  举报

导航