最大流当前弧优化Dinic分层模板

Posted GeekZRF

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大流当前弧优化Dinic分层模板相关的知识,希望对你有一定的参考价值。

最大流模板:

  • 普通最大流
  • 无向图限制:将无向图的边拆成2条方向相反的边
  • 顶点有流量限制:拆成2个点,连接一条容量为点容量限制的边
  • 无源汇点有最小流限制的最大流:理解为水管流量形成循环,每根水管有流量限制,并且流入量等于流出量
  • 有源汇点的最小流限制的最大流
  • 有最小流量限制的最小流
  • 容量为负数:不能直接利用最大流求边权为负数的最小割。不知道怎么具体处理。。。

 

模板使用Dinic分层算法,使用了当前弧优化,效率还是不错的,使用的是vector存图,如果使用邻接表存图效率应该会高一些些吧。

但是ispa算法的效率更高,采用了当前弧优化的ispa算法那就更更高的效率了(=^ ^=),但是这个算法目前不会啊。。。

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
#define PI acos(-1.0)
const int maxn=1e5+100,maxm=1e5+100,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=1e18+7;
struct edge
{
    int from,to,cap,flow;
};
struct Dinic
{
    int n,m,s,t;
    vector<edge>es;
    vector<int>G[maxn];
    bool vis[maxn];
    int dist[maxn],iter[maxn];
    void init(int n,int m)
    {
        this->n=n;
        this->m=m;
        for(int i=0; i<=n+5; i++) G[i].clear();
        es.clear();
    }
    void addedge(int from,int to,int cap)
    {
        es.push_back((edge)
        {
            from,to,cap,0
        });
        es.push_back((edge)
        {
            to,from,0,0
        });
        int x=es.size();
        G[from].push_back(x-2);
        G[to].push_back(x-1);
    }
    bool BFS()
    {
        memset(vis,0,sizeof(vis));
        queue <int> Q;
        vis[s]=1;
        dist[s]=0;
        Q.push(s);
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            for (int i=0; i<G[u].size(); i++)
            {
                edge &e=es[G[u][i]];
                if (!vis[e.to]&&e.cap>e.flow)
                {
                    vis[e.to]=1;
                    dist[e.to]=dist[u]+1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int DFS(int u,int f)
    {
        if(u==t||f==0) return f;
        int flow=0,d;
        for(int &i=iter[u]; i<G[u].size(); i++)
        {
            edge &e=es[G[u][i]];
            if(dist[u]+1==dist[e.to]&&(d=DFS(e.to,min(f,e.cap-e.flow)))>0)
            {
                e.flow+=d;
                es[G[u][i]^1].flow-=d;
                flow+=d;
                f-=d;
                if (f==0) break;
            }
        }
        return flow;
    }
    int Maxflow(int s,int t)
    {
        this->s=s,this->t=t;
        int flow=0;
        while(BFS())
        {
            memset(iter,0,sizeof(iter));
            flow+=DFS(s,inf);
        }
        return flow;
    }

} Dinc;
int in[maxn],out[maxn];
int sign[maxn];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);

    /**有源汇点*/
    int s,t;
    scanf("%d%d",&s,&t);

    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    Dinc.init(n,m);
    for (int i=1; i<=m; i++)
    {
        int u,v,l,r;
        scanf("%d %d %d %d",&u,&v,&l,&r);
        out[u]+=l;
        in[v]+=l;
        sign[i]=l;
        Dinc.addedge(u,v,r-l);
    }

    /**最小流限制有源汇点*/
    Dinc.addedge(t,s,inf);

  /**最小流限制,新增源点0,汇点n+1*/
int all=0,sum=0; for(int i=1; i<=n; i++) { if(in[i]>out[i]) { Dinc.addedge(0,i,in[i]-out[i]); all+=in[i]-out[i]; } else if(in[i]<out[i]) { Dinc.addedge(i,n+1,out[i]-in[i]); sum+=(in[i]-out[i]); } } if(Dinc.Maxflow(0,n+1)!=all) puts("NO"); else { puts("YES"); /**有源汇点*/ sum=-Dinc.es[2*m+1].flow; Dinc.es[2*m+1].flow=0; Dinc.es[2*m].flow=0; Dinc.es[2*m].cap=0; sum+=Dinc.Maxflow(s,t); printf("%d\n",sum); /**无源汇点:可以理解成水管相连,每根水管的水流入量等于流出量,所有水管形成循环*/ for(int i=0; i<m*2; i+=2) printf("%d\n",Dinc.es[i].flow+sign[i/2+1]);///每根水管的流量情况 } return 0; }

 

以上是关于最大流当前弧优化Dinic分层模板的主要内容,如果未能解决你的问题,请参考以下文章

P3376 模板网络最大流(luogu)

P3376 (最大流 dinic)

luogu3376 模板网络最大流 dinic

有源汇带上下界最小流

DINIC网络流+当前弧优化

dinic及当前弧优化