zoukankan      html  css  js  c++  java
  • 【模板】最小费用最大流

    题目描述:

    给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

    题解:

    这是最小费用最大流模板。

    对于EK算法,我们可以通过bfs找出增广路径然后解出最大流。

    但是最大流值是一定的,流法却有很多。

    我们可以将每条边费用作这条边的边长,用spfa求出最短增广路。

    其实就是将EK中的bfs换成spfa。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 5050
    #define M 50050
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,m,S,T,hed[N],cnt=-1;
    struct EG
    {
        int to,nxt,vl,w;
    }e[2*M];
    void ae(int f,int t,int v,int w)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        e[cnt].vl = v;
        e[cnt].w = w;
        hed[f]=cnt;
    }
    int maxf,minw;
    int dis[N],fl[N],pre[N],fa[N];
    bool vis[N];
    const int inf = 0x3f3f3f3f;
    bool spfa()
    {
        memset(dis,0x3f,sizeof(dis));
        memset(fl,0,sizeof(fl));
        memset(vis,0,sizeof(vis));
        dis[S]=0,fl[S]=inf,vis[S]=1,pre[T]=-1;
        queue<int>q;
        q.push(S);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u]=0;
            for(int j=hed[u];~j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(e[j].vl&&dis[to]>dis[u]+e[j].w)
                {
                    dis[to]=dis[u]+e[j].w;
                    fl[to]=min(fl[u],e[j].vl);
                    pre[to]=j,fa[to]=u;
                    if(!vis[to])
                    {
                        vis[to]=1;
                        q.push(to);
                    }
                }
            }
        }
        return pre[T]!=-1;
    }
    void mcmf()
    {
        while(spfa())
        {
            minw+=dis[T]*fl[T];
            maxf+=fl[T];
            int tmp = T;
            while(tmp!=S)
            {
                e[pre[tmp]].vl-=fl[T];
                e[pre[tmp]^1].vl+=fl[T];
                tmp=fa[tmp];
            }
        }
    }
    int main()
    {
        n=rd(),m=rd(),S=rd(),T=rd();
        memset(hed,-1,sizeof(hed));
        for(int f,t,v,w,i=1;i<=m;i++)
        {
            f=rd(),t=rd(),v=rd(),w=rd();
            ae(f,t,v,w),ae(t,f,0,-w);
        }
        mcmf();
        printf("%d %d
    ",maxf,minw);
        return 0;
    }
  • 相关阅读:
    vue相关坑
    jQuery上传文件按钮美化
    大屏幕数据可视化问题
    jquery实现点击页面空白处,弹框消失
    知识点
    js数字串传参时变科学计数法
    jQuery循环遍历取值
    如何判断一个弹框是打开还是关闭状态?
    js库写法
    React版本修改内容
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10000478.html
Copyright © 2011-2022 走看看