最大流(BFS)

先给出最大流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,每得到一条边就添加残余流量,同时反向的要取负值

posted @ 2012-11-22 23:35  Titanium  阅读(870)  评论(0编辑  收藏  举报