zoukankan      html  css  js  c++  java
  • 最大流(二)—— SAP算法

    直接上代码

    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<queue>
    #define numm ch-48
    #define pd putchar(' ')
    #define pn putchar('
    ')
    #define pb push_back
    #define fi first
    #define se second
    #define fre1 freopen("1.txt","r",stdin)
    #define fre2 freopen("2.txt","w",stdout)
    using namespace std;
    template <typename T>
    void read(T &res) {
        bool flag=false;char ch;
        while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
        for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
        flag&&(res=-res);
    }
    template <typename T>
    void write(T x) {
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
    }
    const int maxm=8000010;     ///有反向边,边数要开两倍
    const int maxn=1000010;
    const int inf=0x3f3f3f3f;
    const int INF=0x7fffffff;
    typedef long long ll;
    struct node {   ///链式前向星
        ll c;
        int to,net;
    }e[maxm];
    int head[maxn],cur[maxn],numh[maxn],h[maxn],pre[maxn];
    ///head:链式前向星头结点数组
    ///cur:当前弧数组
    ///numh:GAP优化的统计高度数量数组
    ///h:距离标号数组
    ///pre:前驱数组
    int n,cnt=0;
    void init() {
    //    cnt=0;
    //    for(int i=1;i<=n;i++)   ///单测试用例可不用
    //        h[i]=0,numh[i]=0;
        for(int i=1;i<=n;i++)
            head[i]=-1,pre[i]=-1;
    }
    void add(int u,int v,ll c) {
        e[cnt].to=v;
        e[cnt].c=c;
        e[cnt].net=head[u];
        head[u]=cnt++;
    }
    ll SAP_Max_Flow(int st,int ed) {
        ll max_flows=0;  ///最大流
        int i,u=st;
        numh[0]=n;
        for(int i=1;i<=n;i++)
            cur[i]=head[i];
        while(h[st]<n) { ///h[st]>=N时,网络中肯定出现了GAP(分层)
            if(u==ed) {
                int neck;   ///瓶颈
                ll minn=INF;
                for(i=st;i!=ed;i=e[cur[i]].to)
                    if(minn>e[cur[i]].c) {
                        minn=e[cur[i]].c;
                        neck=i;
                    }
                for(i=st;i!=ed;i=e[cur[i]].to) {
                    int tmp=cur[i];
                    e[tmp].c-=minn;
                    e[tmp^1].c+=minn;
                }
                max_flows+=minn;
                u=neck;
            }
            for(i=cur[u];i!=-1;i=e[i].net)
                if(e[i].c&&h[u]==h[e[i].to]+1)
                    break;      ///寻找可行弧
            if(i!=-1) {
                cur[u]=i;
                pre[e[i].to]=u;
                u=e[i].to;
            }
            else {
                if(--numh[h[u]]==0) break;
                cur[u]=head[u];
                int tmp;
                for(tmp=n,i=head[u];i!=-1;i=e[i].net)
                    if(e[i].c)
                       tmp=min(tmp,h[e[i].to]);
                h[u]=tmp+1;
                numh[h[u]]++;
                if(u!=st) u=pre[u]; ///重标号并从当前点前驱重新增广
            }
        }
        return max_flows;
    }
    int main()
    {
        int st,m,ed;
        read(n),read(m),read(st),read(ed);
        init();
        for(int i=1;i<=m;i++) {
            int u,v;
            ll c;
            read(u),read(v),read(c);
            add(u,v,c);
            add(v,u,0);     ///建立反向边
        }
        write(SAP_Max_Flow(st,ed));
        return 0;
    }
    ///SAP算法:GAP优化+当前弧优化
    

      

  • 相关阅读:
    Python-产生随机长度的密码
    Python-双色球
    Python-产生手机号码
    Word操作笔记
    1035 最长的循环节
    B. Recover the String
    uva11752 The Super Powers
    UVA11754
    GCD
    D. Persistent Bookcase(Codeforces Round #368 (Div. 2))
  • 原文地址:https://www.cnblogs.com/wuliking/p/11200564.html
Copyright © 2011-2022 走看看