zoukankan      html  css  js  c++  java
  • 最小费用最大流+(对最小费用最大流的理解)

    题目链接:https://cn.vjudge.net/contest/68128#problem/E

    具体思路:图的建立方式, 超级源点 - >  供应商 - > 顾客 - > 超级汇点。

    因为有多种商品,所以可以简化构图过程,每一次求一种商品的最小费用最大流,然后最终将所有商品的最小费用最大流的总和加起来就可以了,注意条件在代码中解释。

    注意: 对于源点到供应商这一段不能设置成inf,具体例子如下所示。

    s -  >s1,同时s1 - >s2,s1 - > s3。这样的话,就相当于有两条路从s出发,本来s到s1的流量总和为5,但是如果把流量设置成inf,

    那么如果本来s1 - >s2,s1 - > s3这两条路的和是超过5的,也就是说按照原来的建图方式,初始从s-> s1 的流量是不够用的,如果改成inf的话,流量就够用,那么就改变题意了。

    AC代码:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<stdio.h>
    using namespace std;
    # define inf 0x3f3f3f3f
    # define maxn 150+100
    # define ll long long
    int need[maxn][maxn];
    int store[maxn][maxn];
    int Map[maxn][maxn][maxn];// i - > numofstore ,j- > huowu ,k - > keeper
    int sum1[maxn],sum2[maxn];
    int head[maxn];
    int dis[maxn],prev[maxn],pree[maxn];
    int vis[maxn];
    int num;
    struct Edge
    {
        int to;
        int cost;
        int w;
        int nex;
    } edge[maxn];
    void addage(int fr,int to,int w,int cost)
    {
        edge[num].to=to;
        edge[num].w=w;
        edge[num].cost=cost;
        edge[num].nex=head[fr];
        head[fr]=num++;
        edge[num].to=fr;
        edge[num].w=0;
        edge[num].cost=-cost;
        edge[num].nex=head[to];
        head[to]=num++;
    }
    bool spfa(int st,int ed)
    {
        memset(vis,0,sizeof(vis));
        memset(pree,-1,sizeof(pree));
        memset(dis,inf,sizeof(dis));
        dis[st]=0;
        vis[st]=1;
        queue<int>q;
        q.push(st);
        while(!q.empty())
        {
            int top=q.front();
            q.pop();
            vis[top]=0;
            for(int i=head[top]; i!=-1; i=edge[i].nex)
            {
                int temp=edge[i].to;
                if(edge[i].w>0&&dis[temp]>dis[top]+edge[i].cost)
                {
                    dis[temp]=dis[top]+edge[i].cost;
                    pree[temp]=top;
                    prev[temp]=i;
                    if(vis[temp]==0)
                    {
                        vis[temp]=1;
                        q.push(temp);
                    }
                }
            }
        }
        return pree[ed]!=-1;
    }
    int mincostflow(int st,int ed)
    {
        int ans=0;
        while(spfa(st,ed))
        {
            int minn=inf;
            for(int i=ed; i!=st; i=pree[i])
            {
                minn=min(minn,edge[prev[i]].w);
            }
            ans+=minn*dis[ed];//dis代表一个单位的花费,minn代表流量。
            for(int i=ed; i!=st; i=pree[i])
            {
                edge[prev[i]].w-=minn;
                edge[prev[i]^1].w+=minn;
            }
        }
        return ans;
    }
    int main()
    {
        int n,m,k;
        while(~scanf("%d%d%d",&n,&m,&k)&&(n+m+k))
        {
            int flag=0;
            memset(need,0,sizeof(need));
            memset(sum1,0,sizeof(sum1));
            memset(sum2,0,sizeof(sum2));
            memset(Map,0,sizeof(Map));
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=k; j++)
                {
                    scanf("%d",&need[i][j]);
                    sum1[j]+=need[i][j];
                }
            }// xu qiu liang
            for(int i=1; i<=m; i++)
            {
                for(int j=1; j<=k; j++)
                {
                    scanf("%d",&store[i][j]);
                    sum2[j]+=store[i][j];
                }
            }
            for(int i=1; i<=k; i++)
            {
                if(sum1[i]>sum2[i])//判断能否满足构图的条件
                {
                    flag=1;
                }
            }
            for(int h=1; h<=k; h++)
            {
                for(int i=1; i<=n; i++)
                {
                    for(int j=1; j<=m; j++)
                    {
                        scanf("%d",&Map[h][j][i]);// 第j种货物从j仓库到达第i个买家的花费
                    }
                }
            }
            if(flag==1)printf("-1
    ");
            else
            {
                int ans=0;
                for(int h=1; h<=k; h++)
                {
                    memset(head,-1,sizeof(head));
                    num=0;
                    for(int i=1; i<=m; i++)
                    {
                        addage(0,i,store[i][h],0);//注意这里的流量设置,不能设置成inf。
                    }
                    for(int i=1; i<=m; i++)
                    {
                        for(int j=1; j<=n; j++)
                        {
                            addage(i,j+m,inf,Map[h][i][j]);//这里的流量即可以设置成inf,也可以设置成存货。
                        }
                    }
                    for(int i=1; i<=n; i++)
                    {
                        addage(m+i,n+m+1,need[i][h],0);//这里设置成需求量。
                    }
                    ans+=mincostflow(0,n+m+1);
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    基于 jQuery 实现的非常精致的自定义内容滑动条
    异步加载js,Css方法
    jquery ready()的几种实现方法小结
    javascript事件绑定,取消,addEventListener,removeEventListener,attachEvent,detachEvent
    JSONP跨域访问,通过动态加入javascript实现
    抓包
    devops docker笔记
    linux 命令
    ubuntu16 mysql5.7 数据占满磁盘mysql服务停止的恢复方法
    devops kubernates
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262839.html
Copyright © 2011-2022 走看看