码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-08-21 13:27:54      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:style   http   color   os   io   strong   for   数据   

题目链接: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(最小费用最大流,坑题),布布扣,bubuko.com

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

标签:style   http   color   os   io   strong   for   数据   

原文地址:http://blog.csdn.net/wjw0130/article/details/38727255

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!