最大流EK算法模板(BFS实现)

变量解释:

s-源点

d-汇点

r[i][j]-残留网络中结点i和结点j间的流量,初始值为边<i,j>的容量

flow[i]-记录从源点到结点i的路径<s,...,i>可容纳的最大流量,显然由最短板原理,flow[i]为路径<s,...,i>中容量最少的那一段的容量

pre[i]-记录结点i的前驱结点,以便保存增广路径,同时标记已加入队列的结点,避免重复访问

 1 #define min(x, y) ((x) < (y) ? (x) : (y))
 2 
 3 const int maxn = 405;
 4 const int inf = 0x7fffffff;
 5 int r[maxn][maxn];  //记录残留网络的容量 
 6 int flow[maxn];  //标记从源点到当前结点实际还剩多少流量可用
 7 int pre[maxn];  //结点的前驱, 同时标记该节点是否在队列中 
 8 int n, m;
 9 
10 int BFS(int s, int d)  //使用BFS寻找增广路径 
11 {
12     queue<int> que;
13     memset(pre, -1, sizeof(pre));
14     pre[s] = 0;
15     flow[s] = inf;  //初始化源点的流量为无穷大 
16     que.push(s);
17     while(!que.empty())
18     {
19         int cur = que.front();
20         que.pop();
21         for(int i = 1; i <= d; ++i)  //遍历所有的结点 
22         {
23             //原图是没有流向s的流的,但是在剩余网络中有反向边,故残留图中有到s的流,故须判断i != s,但由于已经设定 pre[s] = 0,故
24             //对i != s的判断寓于对pre == -1的判断中
25             if(r[cur][i] > 0 && pre[i] == -1)
26             {
27                  pre[i] = cur;  //记录前驱以保存路径 
28                  flow[i] = min(r[cur][i], flow[cur]);   //关键:迭代地找到增量 
29                  if(i == d) return flow[d];  //抵达汇点,找到增广路径
30                  que.push(i);               
31             }
32         }
33     } 
34     return -1;  //没有流能到达d,残留图中不再存在增广路径        
35 }
36 
37 int EK(int s,int d)
38 {
39     int inc = 0;
40     int max_flow = 0;
41     while((inc = BFS(s, d)) != -1)
42     {
43         for(int i = d; i != s; i = pre[i]) //利用前驱寻找路径
44         {
45             //以下两步更新残留图
46             r[pre[i]][i] -= inc;  //改变正向边的容量
47             r[i][pre[i]] += inc;  //改变反向边的容量
48         }
49         max_flow += inc;
50     }   
51     return max_flow;
52 }
原文地址:https://www.cnblogs.com/cszlg/p/3047281.html