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;
    }
  • 相关阅读:
    LeetCode: Maximum Product Subarray 解题报告
    LeetCode: Populating Next Right Pointers in Each Node II 解题报告
    LeetCode: Populating Next Right Pointers in Each Node 解题报告
    LeetCode: Word Search 解题报告
    C语言文件操作
    多线程
    C语言函数指针的使用
    进程
    网络编程
    进程间通信——管道通信
  • 原文地址:https://www.cnblogs.com/XjzLing/p/8403709.html
Copyright © 2011-2022 走看看