zoukankan      html  css  js  c++  java
  • 最大流当前弧优化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;
    };
    vector<edge>es;
    vector<int>G[maxn];
    bool vis[maxn];
    int dist[maxn];
    int iter[maxn];
    void init(int n)
    {
        for(int i=0; i<=n+10; 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(int s,int t)
    {
        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 t,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,t,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)
    {
        int flow=0;
        while(BFS(s,t))
        {
            memset(iter,0,sizeof(iter));
            int d=0;
            while(d=DFS(s,t,inf)) flow+=d;
        }
        return flow;
    }
    
    int in[maxn],out[maxn];
    int l[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));
        init(n);
        for (int i=1; i<=m; i++)
        {
            int u,v,r;
            scanf("%d %d %d %d",&u,&v,&l[i],&r);
            out[u]+=l[i],in[v]+=l[i];
            addedge(u,v,r-l[i]);
        }
    
        /**有源汇点有下界*/
        addedge(t,s,inf);
    
        /**有下界添加新源点0,汇点n+1*/
        int ss=0,tt=n+1;
        int sum=0;
        for(int i=1; i<=n; i++)
        {
            if(in[i]>out[i])
            {
                addedge(ss,i,in[i]-out[i]);
                sum+=in[i]-out[i];
            }
            else if(in[i]<out[i])
                addedge(i,tt,out[i]-in[i]);
        }
    
        /**无下界直接用s,t求最大流*/
        if(Maxflow(ss,tt)!=sum) puts("NO");
        else
        {
            puts("YES");
    
            /**有源汇点*/
            int ans=-es[2*m+1].flow;
            es[2*m+1].flow=0;
            es[2*m].flow=0;
            es[2*m].cap=0;
            ans+=Maxflow(s,t);///ans-=Maxflow(t,s);///最小流
            printf("%d
    ",ans);
    
            /**无源汇点:可以理解成水管形成循环*/
            for(int i=0; i<m*2; i+=2)
                printf("%d
    ",es[i].flow+l[i/2+1]);///每根水管的流量情况
        }
        return 0;
    }
  • 相关阅读:
    java学习day28-jQuery(常用)
    在博客园上添加bilibili视频
    参数传递 实参
    linux 下office软件推荐
    桥后总结 二
    go基础笔记-包
    Linux:Day24(上)
    Linux:Day23(下) vsftpd
    Linux:Day23(上) MariaDB SQL语句
    Linux:Day22(下) php及mysql使用基础
  • 原文地址:https://www.cnblogs.com/GeekZRF/p/7289716.html
Copyright © 2011-2022 走看看