zoukankan      html  css  js  c++  java
  • [模板]网络最大流 & 最小费用最大流

    我的作业部落有学习资料

     可学的知识点

    Dinic 模板

    #define rg register
    #define _ 10001
    #define INF 2147483647
    #define min(x,y) (x)<(y)?(x):(y)
    using namespace std;
    int n,m,s,t,record[_],num_of_edges=-1,cur[_],team[10000001],depth[_];
    struct pp
    {
        int next,to,w;
    }edge[(_<<4)+(_<<2)];
    inline int read()
    {
        rg int save=0,w=1;rg char q=getchar();
        while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
        while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
        return save*w;
    }
    inline void add(rg int from,rg int to,rg int ww)
    {
        edge[++num_of_edges]=(pp){record[from],to,ww};
        record[from]=num_of_edges;
    }
    inline bool bfs()
    {
        rg int head=0,tail=1;
        for(rg int i=1;i<=n;++i)depth[i]=0;//depth[]初值为-1,免得返回出发点
        depth[s]=1;
        team[1]=s;
        do
        {
            head++;
            rg int u=team[head];
            for(rg int j=record[u];j!=-1;j=edge[j].next)
            {
                rg int to=edge[j].to;
                if((!depth[to])&&(edge[j].w>0))
                {
                    depth[to]=depth[u]+1;
                    team[++tail]=to;
                    if(to==t)return 1;
                }
            }
        }while(head<tail);
        return 0;
    }
    int dfs(rg int u,rg int flow)//找到每条路上的最小残余流量,因此需在回溯时更新每条边的流量
    {
        if(u==t)return flow;
        for(rg int &j=cur[u]/*当前弧优化*/;j!=-1;j=edge[j].next)
        {
            rg int to=edge[j].to;
            if(depth[to]==depth[u]+1&&(edge[j].w>0))
            {
                rg int D=dfs(to,min(flow,edge[j].w));//到终点的过程中一直在取min
                if(D>0)
                {
                    edge[j].w-=D,edge[j^1].w+=D;
                    return D;//每次只找一条可流通路满上(这里就不管现实中物理的联通器原理了)
                }
                
            }
        }
        return 0;
    }
    inline int Dinic()
    {
        rg int i,j,ans=0;
        while(bfs())
        {
            for(i=1;i<=n;++i)cur[i]=record[i];
            while(int now=dfs(s,INF))ans+=now;
        }
        return ans;
    }
    int main()
    {
        n=read(),m=read(),s=read(),t=read();
        rg int i,j;
        for(i=1;i<=n;++i)record[i]=-1;
        for(i=1;i<=m;++i)
        {
            rg int x=read(),y=read(),ww=read();
            add(x,y,ww),add(y,x,0);
        }
        printf("%d
    ",Dinic());
        return 0;
    }

     最小费用最大流:

    #define rg register
    #define _ 5001
    #define __ 50001
    #define INF 2147483647
    using namespace std;
    int n,m,s,t,record[_],num_of_edges=1,pre[_],res_flow,res_cost,dis[_],team[__<<4];//以后num_of_edges都赋为 1 !!!
    bool exist[_];
    struct pp
    {
        int next,to,w,cost;
    }edge[__<<1];
    inline int read()
    {
        rg int save=0,w=1;rg char q=getchar();
        while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
        while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
        return w*save;
    }
    inline void add(rg int from,rg int to,rg int ww,rg int f)
    {
        edge[++num_of_edges]=(pp){record[from],to,ww,f};
        record[from]=num_of_edges;
    }
    inline bool SPFA()
    {
        rg int head=0,tail=1;
        for(rg int i=1;i<=n;++i)exist[i]=0,dis[i]=INF;
        dis[s]=0;
        team[1]=s;
        do
        {
            head++;
            rg int i=team[head];
            exist[i]=0;
            for(rg int j=record[i];j;j=edge[j].next)
            {
                rg int to=edge[j].to;
                if(edge[j].w>0&&dis[to]>dis[i]+edge[j].cost)
                {
                    dis[to]=dis[i]+edge[j].cost;
                    pre[to]=j;
                    if(!exist[to])team[++tail]=to,exist[to]=1;
                }
            }
        }while(head<tail);
        return dis[t]!=INF;
    }
    inline void doit()
    {
        while(SPFA())
        {
            rg int flow=INF;
            for(rg int i=pre[t];i;i=pre[edge[i^1].to])
                flow=min(flow,edge[i].w);
            res_flow+=flow;
            res_cost+=dis[t]*flow;
            for(rg int i=pre[t];i;i=pre[edge[i^1].to])
                edge[i].w-=flow,edge[i^1].w+=flow;
        }
        printf("%d %d
    ",res_flow,res_cost);
    }
    int main()
    {
        n=read(),m=read(),s=read(),t=read();
        rg int i,j;
        for(i=1;i<=m;++i)
        {
            rg int u=read(),v=read(),w=read(),f=read();
            add(u,v,w,f),add(v,u,0,-f);
        }
        doit();//实在不想用那个MCMF()
        return 0;
    }
  • 相关阅读:
    zlib编译不过(Error A2070)解决方法(转)
    error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CStaticLink::* )(CPoint)' to 'LRESULT (__thiscall CWnd::* )(CPoint) (转)
    MFC does not support WINVER less than 0x0501 解决方案(转)
    【程序打包工具 Inno Setup】转
    【Visual Studio】简单内存泄漏检测方法 解决 Detected memory leaks! 问题(转)
    各种版本QT下载地址与VS2013+QT5.3.1环境搭建过程(转)
    【Windows Message】MFC 通过F5,刷新桌面
    [bzoj]3343 教主的魔法
    NOIP2012 国王游戏
    NOIP模拟赛 路面修整
  • 原文地址:https://www.cnblogs.com/c-wen/p/9390803.html
Copyright © 2011-2022 走看看