网络流 最大流 Edmonds-Karp算法

  Edmonds-Karp算法,复杂度O(VE^2)。思想就是找增广路,不断增加流量。在残量(每条边上流量和容量的差)图上找一条每个边权值都为正的路(可以通过BFS,比DFS效率高),这些边权值里的最小值就是这条路可以增加的流量,然后在这条路径上更新流量。再重复找这样的路更新流量,直到找不到这样的路了就说明流量不能再增加了,当前的流就已经是最大流。

  同时最大流也是最小割(权值和最小的割集)。设起点s,终点t,最后不能再更新的时候,a[u](u点可增流量)不为0的点放到S集合中,剩下的点放到T集合中,(S,T)就是s-t的最小割,f=c(S,T)。(跨越S,T的边一定都是满载,并且都是每条路上权值最小的边)。

int Edmonds_Karp(){  //s,t为起点、终点
    queue<int> q;
    memset(flow,0,sizeof(flow));
    int f=0;  //最大流
    while(1){
        memset(a,0,sizeof(a)); //a是每个结点可增流量
        a[s]=INF;  //起点有无限大的流量
        q.push(s);
        while(!q.empty()){  //BFS
            int u=q.front();
            q.pop();
            for(int v=0;v<=N;v++) if(!a[v]&&flow[u][v]<cap[u][v]){  //省去vis数组,因为若a[v]不为0,说明访问过。流量小于容量说明残量图有边
                a[v]=min(a[u],cap[u][v]-flow[u][v]);
                p[v]=u;  //记录路径
                q.push(v);
            }
        }
        if(!a[t]) break;  //不能再增加流量
        for(int u=t;u!=s;u=p[u]){
            flow[p[u]][u]+=a[t];   //更新正向流量
            flow[u][p[u]]-=a[t];   //更新反向流量
        }
        f+=a[t]; //更新最大流
    }
    return f;
}


你可能感兴趣的:(网络流 最大流 Edmonds-Karp算法)