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;
    }
  • 相关阅读:
    MQ 2035(MQRC_NOT_AUTHORIZED)
    C# 构造函数中调用虚方法的问题
    Oracle bug 使用max或min函数into到一个char类型报字符缓冲区太小的错误
    windows2003 64位 iis6.0 运行32位web应用程序
    .NET安装和配置Oracle数据访问组件(ODAC)
    WMS函数组:10.创建采购订单
    报表:BOM展开程序
    WMS函数组:9.交货单过帐3(BDC)
    WMS函数组: 7.交货单行项目除
    WMS函数组:1.检查ZPB2是否存在
  • 原文地址:https://www.cnblogs.com/XjzLing/p/8403709.html
Copyright © 2011-2022 走看看