先给出最大流BFS模板,其实就是白书上面的
void BFS() { flow=0; while(!q.empty()) q.pop(); while(1) { memset(a,0,sizeof(a)); a[s]=INF; q.push(s); while(!q.empty()) { int u; u=q.front(); q.pop(); for(int v=1; v<=n; v++) //枚举所有点v; <u,v> if(!a[v] && c[u][v]>f[u][v]) { p[v]=u; q.push(v); a[v]=a[u]<c[u][v]-f[u][v] ? a[u] : c[u][v]-f[u][v]; //递推 } } if(!a[t]) break; for(int u=t; u!=s; u=p[u]) { f[p[u]][u]+=a[t]; f[u][p[u]]-=a[t]; } flow+=a[t]; } return ; }
整个算法用文字来描述就是
1.建好图,注意有些图是特意搞成无向图,那么就当做有两条方向相反的边,容量相同来处理即可,也就是建图的时候处理就行了,不关BFS的事
其中c数组就保存容量,当边(u,v)不存在时c[u][v]=0; f[u][v]表示边(u,v)当前的流量
2.初始化当前流量为0,即一开始是0流,然后开始增广路
a数组在每趟bfs中找到最小路径中最小残余流量的,a数组使个递推数组,a[v]的意思是从源点s到点v的最小残余流量
所以看这个更新
a[v]=a[u]<c[u][v]-f[u][v] ? a[u] : c[u][v]-f[u][v];
因为边(u,v),所以路径时s………………>u->v,那么a[u]就是s到u的最小残余流量,那么u到v这条边的残余流量表是 c[u][v]-f[u][v] , 就取两者中的较小值赋值给a[v]
所以a[t] (t是汇点)的意思就是从s到t(即完整的路径)的最小残余流量,如果a[t]=0,也就是没有找不到,那么说明已经无法增广路了,不能再添加残余流量了,那说明算法已 经结束了; 每次bfs结束后的最后一句 flow+=a[t]; flow是最后的答案,最大流,最大流其实就是每次求出的残余流量的和
3.bfs的话没什么特别,就是寻找路径,就跟图的遍历一样,遍历我们用vis[v]来标记点v是否被访问过,这里因为a数组是每次bfs开始前清0,所以a数组其实代替了vis的作用,我们可以看到在bfs寻找路径的过程,每个点只会被访问一次(跟遍历一样嘛)。当然因为是寻找路径所以需要p数组来记录前驱
4.每次bfs结束之后,要干什么,没错就是把找到的最小残余流量添加到那条路径的每个流量中,所以记录前驱的p数组就派上用场,不断地迭代,从汇点t回到原点s,每得到一条边就添加残余流量,同时反向的要取负值