最大流—— SAP算法

Posted wuliking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大流—— SAP算法相关的知识,希望对你有一定的参考价值。

直接上代码

#include<vector>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<queue>
#define numm ch-48
#define pd putchar(‘ ‘)
#define pn putchar(‘\n‘)
#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优化+当前弧优化

  

以上是关于最大流—— SAP算法的主要内容,如果未能解决你的问题,请参考以下文章

最大流的SAP算法模板

网络流:最大流之Dinic算法

hiho一下 第115周:网络流一?Ford-Fulkerson算法 (Edmond-Karp,Dinic,SAP)

BZOJ1066 [SCOI2007]蜥蜴 网络流 最大流 SAP

最大流sap

ISAP网络流算法