• 【模板】网络流(Dinic)


    //洛谷P3376

    对于最大流是什么,各位可以Baidu一下,简而言之,就是求一个有向图中,从源点(S)到汇点(T)流量(Flow)的最大流通量。

    而对于这个方案的求解,我们肯定首先想到的是按照上面这三个原理进行贪心......

    然后一顿贪心以后,发现找的的不一定是最优解,因为,有时。

    所以我们引进Dinic算法:

    • 在建图的时候,我们建立一条反向边,并用e[i^1]去存(想一想为什么)
    struct edge{
        int to,flow;
    }e[N*2];
    int fst[N],nxt[N],cnt;
    void addedge(int x,int y,int f){
        e[cnt]=(edge){y,f};
        nxt[cnt]=fst[x],fst[x]=cnt++;
        e[cnt]=(edge){x,0};
        nxt[cnt]=fst[y],fst[y]=cnt++;
    }
    • 然后开始搜索
    • 首先是Bfs:
    •     从S开始,逐渐Bfs,把没有分层的点分成layer[x]+1再压入队列
    •     若T已被分层,则代表原图有增广路
    •     否则则原图已经没有增广路,已经是最优解
    • 然后是Dfs
    •    逐渐增广以致最优解

    简而言之一句话:while(Bfs()) dfs();

    最后是代码(数组邻接表格式):

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define _int long long
    #define N 200000 + 10 
    #define INF 2147483647
    using namespace std;
    struct edge{
        int to,flow;
    }e[N*2];
    int n,m,S,T;
    int fst[N],nxt[N],cnt;
    int layer[N];
    void addedge(int x,int y,int f){
        e[cnt]=(edge){y,f};
        nxt[cnt]=fst[x],fst[x]=cnt++;
        e[cnt]=(edge){x,0};
        nxt[cnt]=fst[y],fst[y]=cnt++;
    }
    bool bfs(){
        memset(layer,-1,sizeof(layer));
        queue<int> que;
        que.push(S);
        layer[S]=0;
        while(!que.empty()){
            int x=que.front();que.pop();
            for(int i=fst[x];i!=-1;i=nxt[i]){
                if(layer[e[i].to]==-1&&e[i].flow>0){
                    layer[e[i].to]=layer[x]+1;
                    que.push(e[i].to);
                }
            }
        }
        if(layer[T]<=0) return false;
        else return true;
    }
    int dfs(int u,int v,int f){
        if(u==v || f==0) return f;
        for(int i=fst[u];i!=-1;i=nxt[i]){
            if(e[i].flow>0&&layer[e[i].to]==layer[u]+1){
                int d=dfs(e[i].to,v,min(f,e[i].flow));
                if(d>0){
                    e[i].flow-=d;
                    e[i^1].flow+=d;
                    return d;
                }
            }    
        }
    } 
    int Dinic(){
        int f=0;
        while(bfs()) f+=dfs(S,T,INF);
        return f;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&S,&T);
        memset(fst,-1,sizeof(fst));
        memset(nxt,-1,sizeof(nxt));
        for(int i=0;i<m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
        }
        printf("%d",Dinic());
        return 0;
    }
  • 相关阅读:
    电商第一季函数笔记(1)
    沈逸老师PHP魔鬼特训笔记(2)
    PHP读书笔记(3)-常量
    2015/8/9 到家了,学完了CodeCademy的Python
    2015/8/4 告别飞思卡尔,抛下包袱上路
    2015/6/23 浪潮过去,我才来
    方维团购系统二次开发,项目经验
    方维团购系统整合云短信网短信平台,方维系统整合短信平台
    方维团购系统,下订单保存多个收货地址
    PHP木马查杀文件,木马查杀插件
  • 原文地址:https://www.cnblogs.com/XjzLing/p/8403709.html
Copyright © 2020-2023  润新知