POJ 2516 Minimum Cost(最小费用最大流,坑题)

题目链接:http://poj.org/problem?id=2516

题意:有N个店,M个供货商,K种商品。已知供货商的仓库里每种商品的数量以及每种商品运送到每个店的费用,每个店铺对各种商品的需求数量,求最少话费。

Input 

第一行:N,M,K。

然后1 - N行,每行 K列 ,第I行第J个数代表 第I个店铺 需要第J种物品多少件。

然后 N+1 - M行  ,每行 K列 , 第I行第J个数代表 第I个供货商 有第J种物品多少件。

然后是K个矩阵  ,每个N行M列,第ji个矩阵的第i行第j列代表着第j个供货商给第i个店铺发第ji种货物一件需要的费用。哎哟,我日

坑题一道啊,感觉已经不是在考查网络流,而是在考察对 繁琐数据输入 的Debug能力,弄了一上午,坑我啊。。。

思路一开始思路就是错的,上去就拆点,将供货商和店铺对应着K种商品,把每个供货商拆成K个,店铺拆成K个,写了一半感觉不对劲,50*50 + 50*50 + 50,肯定超时。

    既然拆点不行,那么就拆网呗。。。把对应所有商品的整个网络,拆成K个单种商品的网络,求出单个商品的最小费用,最后进行累加即可

建图:

增设两个点,源点s = 0,汇点t = N+M+1,源点与供货商相连,费用0,容量为当前单种商品的供给量

供货商与店铺相连费用已知,容量为正无穷。

店铺与汇点相连,费用0,容量为当前单种商品的需求。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
const int maxn = 110;
const int maxm = 10000;
const int inf = 1e8;
#define MIN INT_MIN
#define MAX 1e6
#define LL long long
#define init(a) memset(a,0,sizeof(a))
#define FOR(i,a,b) for(int i = a;i<b;i++)
#define max(a,b) (a>b)?(a):(b)
#define min(a,b) (a>b)?(b):(a)
using namespace std;
struct node
{
    int u,v,w,cap,next;
}edge[maxm];
int pre[maxn],dis[maxn],head[maxn],cnt;
bool vis[maxn];
int n,m;
void add(int u,int v,int c,int cap)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].w=c;
    edge[cnt].cap=cap;
    edge[cnt].next=head[u];
    head[u]=cnt++;

    edge[cnt].u=v;
    edge[cnt].v=u;
    edge[cnt].w=-c;
    edge[cnt].cap=0;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
int spfa(int s,int t)
{
    queue<int>q;
    while(q.empty()==false) q.pop();
    q.push(s);
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    FOR(i,s,t+1)
        dis[i] = inf;
    dis[s]=0;
    while(!q.empty())
    {
       int u=q.front();
        q.pop();
        vis[u] = 0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            if(edge[i].cap && dis[edge[i].v]>dis[u]+edge[i].w)
            {
                dis[edge[i].v]=dis[u]+edge[i].w;
                pre[edge[i].v] = i;
                if(!vis[edge[i].v])
                {
                    vis[edge[i].v]=1;
                    q.push(edge[i].v);
                }
            }
        }

    }
    if(dis[t] != inf)
        return 1;
    else
        return 0;
}
int MinCostMaxFlow(int s,int t)
{
	int flow=0,cost=0;
    while(spfa(s,t))
    {
		int df = inf;
		for(int i = pre[t];i!=-1;i=pre[edge[i].u])
		{
			if(edge[i].cap<df)
				df = edge[i].cap;
		}
		flow += df;
        for(int i=pre[t];i!=-1;i=pre[edge[i].u])
        {
            edge[i].cap -= df;
            edge[i^1].cap += df;
        }
	cost += dis[t] * df;
    }
    return cost;
}
void initt()
{
    cnt=0;
    memset(head,-1,sizeof(head));
}

int main()
{
    int gong[51],qiu[51];
    int k,s,t;
    int need[200][200],gei[200][200];
    while(scanf("%d%d%d",&n,&m,&k),n,m,k)
    {
        init(need);init(gei);
        init(gong);init(qiu);
        s = 0,t = n+m+1;
        FOR(i,1,n+1)
        {
            FOR(j,1,k+1)
                {
                    scanf("%d",&need[i][j]);
                    qiu[j] += need[i][j];
                }
        }
        FOR(i,1,m+1)
        {
            FOR(j,1,k+1)
            {
                scanf("%d",&gei[i][j]);
                gong[j] += gei[i][j];
            }
        }
        bool flag = 1;
        FOR(i,1,k+1)
        {
            if(gong[i]<qiu[i])//如果单种商品的供给量不满足该商品的需求量,直接打印-1
            {
                flag = 0;
                break;
            }
        }
        int cost,yao,money = 0;

        FOR(ji,1,k+1)
        {
             initt();

             FOR(i,1,n+1)
             {
                FOR(j,1,m+1)
               {
                   scanf("%d",&cost);
                   if(flag==0) continue;
                   add(j,m+i,cost,inf);//供给商和店主的流量为正无穷
               }
             }
             if(flag==0) continue;
             FOR(i,1,n+1)
             {
                 add(m+i,t,0,need[i][ji]);//店铺和汇点的费用为0,流量为店对该种商品的需求
             }
             FOR(i,1,m+1)
             {
                 add(s,i,0,gei[i][ji]);//源点对供应商的费用为0,流量为供货商对该种商品的供给
             }
           money += MinCostMaxFlow(s,t);
        }
        (flag==0)?puts("-1"):printf("%d\n",money);
    }
    return 0;
}

POJ 2516 Minimum Cost(最小费用最大流,坑题)

时间: 2024-07-31 00:42:52

POJ 2516 Minimum Cost(最小费用最大流,坑题)的相关文章

POJ 2516 Minimum Cost (最小费用最大流)

Minimum Cost Time Limit: 4000MS   Memory Limit: 65536K       Description Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (marked from 1 to N) which stocks goods from him.Dearboy

Poj 2516 Minimum Cost (最小花费最大流)

题目链接: Poj  2516  Minimum Cost 题目描述: 有n个商店,m个仓储,每个商店和仓库都有k种货物.嘛!现在n个商店要开始向m个仓库发出订单了,订单信息为当前商店对每种货物的需求量.不同的商店从不同的仓库购买不同货物花费不同,问是不是能满足所有商店的要求,如果能商店花费总和最小为多少? 解题思路: 简单的费用流,要跑K次最小花费最大流,每次只对一种货物建图跑费用流.每次建图以0为源点, [1,m]为仓库, [m+1, n+m]为商店, n+m+1为汇点.0与[1,m]连边,

POJ 2516 Minimum Cost 【费用流】

建模比较难想.. #include<iostream> #include<deque> #include<vector> #include<cstring> #include<cmath> #define INF 2e9 using namespace std; int T,ans; struct edge{ int v,cap,reverse,cost; }; vector<int> edges[1005];//邻接表 vector

POJ 2516 Minimum Cost (最小费用最大流)

POJ 2516 Minimum Cost 链接:http://poj.org/problem?id=2516 题意:有M个仓库,N个商人,K种物品.先输入N,M,K.然后输入N行K个数,每一行代表一个商人要购买的物品,其中K个数分别表示要购买的每件商品数.然后是M行K个数,每行表示仓库里的情况,其中K个数分别每种物品的库存量.接下来是K个矩阵,每个矩阵为N*M,分别表示第K种物品从M个仓库运到第N个商人的花费.问能否合理安排,使得花费最少,如果不行就输出-1. 思路: 一开始的时候,竟然构造了

poj 2516 Minimum Cost 【最小费用最大流】

题目:poj 2516 Minimum Cost 题意:有 n 个商店,k种物品和 m 个供货商,让你求进满足商店需求的货物的最小花费? 有必要说一下输入数据. 首先n ,k ,m 然后是一个n*m的矩阵,n个商店对每种货物的需求,表示第 i 个商店需要第 j 种货物 x个 然后是m * k 的矩阵,m个供货商可以供k种货物的数量,表示第 i 个供货商 提供第 j 中货物 x 个 接下来是 k 个 n * m 的矩阵,表示第 i 个货物,由 k 供应商发货给 j 商店的价格x (注意如果供不应求

POJ 2516 Minimum Cost(网络流之费用流)

题目地址:POJ 2516 我晕啊...这题一上来就想到了对每种货物分开求..但是马上就放弃了..感觉这样求50次费用流太耗时..后来就果断拆点,拆了好长时间,一直TLE..即使降到了2600个点也TLE..然后又想起了这个分开求的方法,又突然觉得100个点的费用流几乎不费什么时间..最多也只是求50次而已,还是可以试试的..于是一试居然还真过了... 说到这里,思路应该已经知道了吧.就是对每种货物分开求,因为每种货物是相互独立的.每一次的建图思路就是: 源点与供应商连边,流量权值为供应商这种货

POJ 2516 Minimum Cost(费用流)

POJ 2516 Minimum Cost 题目链接 题意:转一篇题意吧..感觉写的很详细了,優YoU http://blog.csdn.net/lyy289065406/article/details/6742534 思路:一开始是把所有商家的每种物品和所有供应商所有物品连边跑费用流,结果TLE了,因为这样建出来的图,边数会非常的庞大 那么其实转化一下思路,每种物品之间是不会互相影响的,那么把每种物品求出来后,累加起来就是答案了,然后注意这题数据要读完,直接判断错没读完数据就会WA 代码: #

poj 2516 Minimum Cost(最小费最大流)

poj 2516 Minimum Cost Description Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (marked from 1 to N) which stocks goods from him.Dearboy has M supply places (marked from 1 to

POJ 2195 Going Home (最小费用最大流)

题目链接:http://poj.org/problem?id=2195 题意:n*m的矩阵,地图上有若干个人(m)和房子(H),且人与房子的数量一致.man每移动一格费用为1,一个房子只能住一个人.现在要求所有的人出发,都入住房子,求最少话费. 思路:建立一个超级源点和汇点,源点与人相连费用为0,容量为1,人与房子相连,费用为人与房子的距离,容量为1,房子与汇点相连,费用为0,容量为1 #include <iostream> #include <cstdlib> #include