【模板】网络流(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;
}
原文地址:https://www.cnblogs.com/XjzLing/p/8403709.html