最大流、最小割算法

#include<bits/stdc++.h>
using namespace std;
//最小割就是把起点及其他分成一个城市,终点及其他分成一个城市,当两个城市之间的线路的流量都满载时,的分法。
//当最大流算法结束时,flag数组不是0的都是从s可达的,而且不可达的原因是没有残余了,所以就找到了最小割

const int maxn=1001;
int G[maxn][maxn],pre[maxn],n,m,flow[maxn][maxn],a[maxn];//flow是当前的流量 a 代表到某个点的最小残余流量
//通过前驱数组求一条路径,当然结果可能会多了不是这条路径上的点的前驱,因为不一定能一次到
int flg[maxn];
int maxflow(int s,int t){
    int f=0;
    //使用bfs,因为每次都要找一条路径,bfs快
    memset(flow,0,sizeof(flow));
while(1){
    queue<int> q;
    q.push(s);
    memset(flg,0,sizeof(flg));
    memset(pre,0,sizeof(pre));
    memset(a,0x3f3f3f3f,sizeof(a));
    flg[s]=1;//必须设置
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=1;i<=n;i++){
            //有流量剩余
            //因为有残量才能遍历,所以t可能遍历不到
            if(!flg[i]&&G[x][i]!=0&&G[x][i]>flow[x][i]){
                pre[i]=x;
                flg[i]=1;
                //到i的最小=到x的最小 和 x到i的 小的那个
                a[i]=min(a[x],G[x][i]-flow[x][i]);//不用整体的min,因为那条路径不一定在s->t上
                //注意,他没有对a[i]再取最小值,这样就可以保证pre和a[t]是对应的同一条边
                //当然也可以,这个就是取所有可达边的最小值残余的 最小值
                // if(a[i]>min(a[x],G[x][i]-flow[x][i])){
                //     a[i]=min(a[x],G[x][i]-flow[x][i]);
                //     pre[i]=x;
                // }

                // if(i==t) break; //两层循环无法退出
                q.push(i);
            }
        }
        if(x==t) break;//我觉得可以提前终止,如果遍历到了t
    }
    cout<<a[t]<<endl;
    //其实当残量为0时,根本遍历不到
    if(a[t]==0x3f3f3f3f){
        //输出最小割
        cout<<"minimum ge
";
        cout<<"Set S
";
        for(int i=1;i<=n;i++) if(flg[i]) cout<<i<<" ";cout<<endl;
        cout<<"Set T
";
        for(int i=1;i<=n;i++) if(!flg[i]) cout<<i<<" ";cout<<endl;
    }
    if(a[t]==0x3f3f3f3f) return f;//没路径退出

    //有残余,对于pre找到的路径上的每个点,都更新flow
    for(int i=t;i!=s;i=pre[i]){
        //注意到s停,因为用到pre
        flow[pre[i]][i]+=a[t];
        flow[i][pre[i]]-=a[t];//别忘了减,根据流量的定义,对于a-> b->a的边有用
    }
    f+=a[t];
}
}
int main() {
    cin>>n>>m;
    memset(G,0,sizeof(G));
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        G[x][y]=z;
    }
    cout<<maxflow(5,6)<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/MorrowWind/p/13056645.html