題目鏈接http://acm.pku.edu.cn/JudgeOnline/problem?id=1273
本題是最大流算法的簡單應用。
最大網絡流的基本思想很簡單——從某個初始流開始,反復的增加流的流量知道不能再改進為止。最后得到的流將是一個最大流。
定理 設 P 是網絡 G 中從起點到終點滿足一下條件的一條路徑:
(a) 對P中的每條正向邊(i,j), Fij < Cij
(b)對P中的每條反向邊(i,j), Fij > 0
設 D是由P中所有正向邊(i,j)對應的數和P中所有反向邊(i,j)對應的數組成。
Δ =min D
Fij 如果(i,j)不在P中
F*ij={ Fij+ Δ 如果(i,j)在P中且是正向的
Fij-Δ 如果(i,j)在P中且不是正向的
根據上述定理,如果找不到路徑滿足上述定理,那么得到的流便是最大的。我們可以構造一個算法:
1.從一個流開始;
2.尋找一個滿足上述定理的路徑,如果這樣的路徑不存在,則停止,流是最大的;
3.將流過這條路徑的流量增加△,轉到第2行。
Ford-Fulkerson方法是按照上述定理構造,解決最大流問題的有效方法,一般采用深搜策略;而Edmonds-Karp算法是Ford-Fulkerson方法的廣搜的實現;相對而言,后者的效率稍微高一些。
下面是POJ 1273的代碼,采用的是Edmonds-Karp算法。
1
#include <cstdio>
2
#include <queue>
3
const int INF=0x0fffffff;
4
const int SIZE=202;
5
6
int bfs(int (*mat)[SIZE],int start,int end,int* path)
7

{
8
int flow[SIZE];//存儲一次BFS遍歷之后流的可改進量;
9
std::queue<int> q;
10
int i;
11
12
for(i=0;i<SIZE;++i)
13
path[i]=-1;
14
path[start]=0,flow[start]=INF;
15
16
q.push(start);
17
while(!q.empty())
18
{
19
int top=q.front();
20
q.pop();
21
if(top==end) break;
22
for(i=1;i<=end;++i)
23
{
24
if(i != start && path[i]==-1 && mat[top][i])
25
{
26
flow[i]=flow[top]<mat[top][i] ? flow[top] : mat[top][i];
27
q.push(i);
28
path[i]=top;
29
}
30
}
31
}
32
if(path[end]==-1) return -1;
33
return flow[end];
34
35
36
}
37
int Edmonds_Karp(int (*mat)[SIZE],int start,int end)
38

{
39
int maxflow=0,step,cur,pre;
40
int path[SIZE]; /**/////存儲當前已訪問過的節點的增廣路徑;
41
while((step=bfs(mat,start,end,path)) != -1)//找不到增廣路徑時退出
42
{
43
maxflow += step;
44
cur=end;
45
while(cur != start)
46
{
47
pre=path[cur];
48
mat[pre][cur] -= step; //更新正向邊的實際容量
49
mat[cur][pre] += step; //添加反向邊
50
cur=pre;
51
}
52
}
53
return maxflow;
54
}
55
56
int main()
57

{
58
int mat[SIZE][SIZE];
59
int vecNum,edgeNum;
60
int i;
61
int a,b,c;
62
63
while(scanf("%d%d",&edgeNum,&vecNum)!=EOF)
64
{
65
memset(mat,0,sizeof(mat));
66
for(i=0;i<edgeNum;++i)
67
{
68
scanf("%d%d%d",&a,&b,&c);
69
mat[a][b]+=c;
70
}
71
72
int re=Edmonds_Karp(mat,1,vecNum);
73
printf("%d\n",re);
74
75
}
76
return 0;
77
}
78