变量解释:
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 }