zoukankan      html  css  js  c++  java
  • 【模板】网络流(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;
    }
  • 相关阅读:
    day7 面向对象 静态方法 类方法 属性方法 类的特殊成员方法 元类 反射 异常处理
    day6 面向对象 封装 继承 多态 类与实例在内存中的关系 经典类和新式类
    day5 time datetime random os sys shutil json pickle shelve xml configparser hashlib subprocess logging re正则 python计算器
    kafka常用操作命令
    linux基础
    django学习1——初识web应用程序
    mysql数据库(三)——pymysql模块
    mysql数据库(二)——表的查询
    mysql数据库(一)
    Python常用模块——re模块
  • 原文地址:https://www.cnblogs.com/XjzLing/p/8403709.html
Copyright © 2011-2022 走看看