最大流模板(dinic)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/IDrandom/article/details/81545125
//dinic
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxm =120020;
const int maxn =1210;
struct Edge{
    int u,v,w;
    int nxt;
}e[maxm<<1];
struct Queue{
    int a[maxn];
    int st=0,ed=0;
    inline int front(){return a[st];}
    inline int back(){return a[ed];}
    inline void clear(){st=ed=0;}
    inline int empty(){return st==ed;}
    inline int pop(){int p=a[st++];if(st==maxn)st=0;return p;}
    inline void push(int p){a[ed++]=p;if(ed==maxn)ed=0;}
}mq;
int h[maxn],cnt;
int dep[maxn];//节点层次
void init(){
    memset(h,-1,sizeof h);
    cnt=0;
}
void add(int u,int v,int w){
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].nxt=h[u];
    h[u]=cnt++;
    e[cnt].u=v;
    e[cnt].v=u;
    e[cnt].w=0;
    e[cnt].nxt=h[v];
    h[v]=cnt++;
}
int bfs(int s,int t){//源点深度为0
    memset(dep,-1,sizeof dep);
    mq.clear();mq.push(s);dep[s]=0;
    while(!mq.empty()){
        int u=mq.pop();
        for(int i=h[u];~i;i=e[i].nxt){
            int v=e[i].v;
            if(e[i].w>0&&dep[v]==-1){
                dep[v]=dep[u]+1;
                mq.push(v);
                if(v==t)return 1;
            }
        }
    }
    return 0;
}
int dinic(int s,int t){
    int res=0;//最大流
    int top;//栈顶
    int ms[maxn];//栈存增广路(边的标号)
    int cur[maxn];//考虑前向星的遍历方法存点的后继
    while(bfs(s,t)){//如果能分层
        memcpy(cur,h,sizeof h);
        int u=s;
        top=0;
        while(1){
            if(u==t){//找到一条增广路
                int mn=INF;//流量
                int loc;//回溯点
                for(int i=0;i<top;i++){//找该增广路上的可行流
                    if(mn>e[ms[i]].w){
                        mn=e[ms[i]].w;
                        loc=i;
                    }
                }
                for(int i=0;i<top;i++){//更新残留网络
                    e[ms[i]].w-=mn;
                    e[ms[i]^1].w+=mn;
                }
                res+=mn;
                top=loc;
                u=e[ms[top]].u;
            }
            for(int i=cur[u];~i;cur[u]=i=e[i].nxt){
                if(e[i].w!=0&&dep[u]+1==dep[e[i].v])break;
            }
            if(cur[u]!=-1){
                ms[top++]=cur[u];
                u=e[cur[u]].v;
            }else{
                if(top==0)break;
                dep[u]=-1;
                u=e[ms[--top]].u;
            }
        }
    }
    return res;
}
int main(){
    int n,m;
    int s,t;
    while(~scanf("%d%d%d%d",&n,&m,&s,&t)){
        int u,v,w;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        int ans=dinic(s,t);
        printf("%d\n",ans);
    }
    return 0;
}

SAP/ISAP/HLPP均未研究
挖坑:ISAP学习
挖坑:HLPP学习
其实只需要知道大概思想,看看代码应该就会写了。

猜你喜欢

转载自blog.csdn.net/IDrandom/article/details/81545125