最大流——dinic算法

Posted kgxw0430

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大流——dinic算法相关的知识,希望对你有一定的参考价值。

  上回介绍了EP算法,这次来学一个效率更高的算法。我们在做EP算法的时候,每次bfs最多遍历了整个残量网络,但是只找到了一条增广路。所以有可以优化的地方。Dinic算法基于分层图,我们先bfs找到一个合法的有向无环图(图中所有边都有残流,图严格按照拓扑序),然后在这张分层图上通过深度优先搜索找到若干条合法不冲突的增广路,累加到maxflow里。并且可以在dfs里添加剪枝:如果当前点以后找不到残流路径,把它直接从分层图中删掉。

  Dinic算法的时间复杂度为O(n^2*m)。实际运用远远小于这个上界,可以说是比较容易实现的效率最高的网络流算法之一,一般可以处理10^4~10^5的网络。特别的,Dinic算法求解二分图最大匹配的时间复杂度为O(m*sqrt(n))。

//Dinic求二分图最大匹配 
#include<bits/stdc++.h>
using namespace std;
const int inf=1<<29,N=20100,M=2e6+20;
int n,m,e,tot=1,s,t,maxflow,flow,d[N],Next[M],ver[M],lin[N],edge[M];
void add(int x,int y,int c){
    ver[++tot]=y;Next[tot]=lin[x];edge[tot]=c;lin[x]=tot;
    ver[++tot]=x;Next[tot]=lin[y];edge[tot]=0;lin[y]=tot;
}
bool bfs(){
    memset(d,0,sizeof(d));
    queue<int>q;
    q.push(s);d[s]=1;
    while(q.size()){
        int x=q.front();q.pop();
        for(int i=lin[x];i;i=Next[i]){
            int y=ver[i];
            if(edge[i]&&!d[y]){
                d[y]=d[x]+1;
                q.push(y);
                if(y==t) return 1;
            }
        }
    }
    return 0;
}
int dinic(int x,int flow){
    if(x==t) return flow;
    int rest=flow;
    for(int i=lin[x];i&&rest;i=Next[i]){
        int y=ver[i];
        if(d[y]==d[x]+1&&edge[i]){
            int k=dinic(y,min(rest,edge[i]));
            if(!k) d[y]=0;
            rest-=k;
            edge[i]-=k;
            edge[i^1]+=k;
        }
    }
    return flow-rest;
}
int main(){
    scanf("%d%d%d",&n,&m,&e);
    s=0,t=n+m+1;
    for(int i=1;i<=e;++i){
        int x,y;scanf("%d%d",&x,&y);
        if(y>m) continue;
        add(x,y+n,1);
    }
    for(int i=1;i<=n;++i) add(s,i,1);
    for(int i=1;i<=m;++i) add(i+n,t,1);
    while(bfs())
        while(flow=dinic(s,inf)) maxflow+=flow;
    printf("%d
",maxflow);
    return 0; 
}

 

以上是关于最大流——dinic算法的主要内容,如果未能解决你的问题,请参考以下文章

网络流最大流入门(Dinic算法)模板

网络流Dinic(本篇介绍最大流)

网络流最大流之Dinic算法

最大流:Dinic算法

网络流最大流——dinic算法

P3376 网络流-最大流模板题(Dinic+当前弧优化)