HDU 6118 度度熊的交易计划 【最小费用最大流】 (2017"百度之星"程序设计大赛 - 初赛(B))

63 篇文章 0 订阅
30 篇文章 0 订阅

度度熊的交易计划

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1111    Accepted Submission(s): 403


Problem Description
度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题:

喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区。

由于生产能力的区别,第i个片区能够花费a[i]元生产1个商品,但是最多生产b[i]个。

同样的,由于每个片区的购买能力的区别,第i个片区也能够以c[i]的价格出售最多d[i]个物品。

由于这些因素,度度熊觉得只有合理的调动物品,才能获得最大的利益。

据测算,每一个商品运输1公里,将会花费1元。

那么喵哈哈村最多能够实现多少盈利呢?
 

Input
本题包含若干组测试数据。
每组测试数据包含:
第一行两个整数n,m表示喵哈哈村由n个片区、m条街道。
接下来n行,每行四个整数a[i],b[i],c[i],d[i]表示的第i个地区,能够以a[i]的价格生产,最多生产b[i]个,以c[i]的价格出售,最多出售d[i]个。
接下来m行,每行三个整数,u[i],v[i],k[i],表示该条公路连接u[i],v[i]两个片区,距离为k[i]

可能存在重边,也可能存在自环。

满足:
1<=n<=500,
1<=m<=1000,
1<=a[i],b[i],c[i],d[i],k[i]<=1000,
1<=u[i],v[i]<=n
 

Output
输出最多能赚多少钱。
 

Sample Input
  
  
2 1 5 5 6 1 3 5 7 7 1 2 1
 

Sample Output
  
  
23
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6143  6142  6141  6140  6139 
 

Statistic |  Submit |  Discuss |  Note


题目链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=6118

题目大意:

  N个城市,M条公路,每个城市花费a[i]元生产1个商品,但是最多生产b[i]个,以c[i]的价格出售最多d[i]个商品,每条公路每运送1个商品花费e[i],问最大收益

题目思路:

  【最小费用最大流】

  首先很容易想到是网络流问题,城市之间连得公路容量∞,费用为e[i],

  源S到每个城市建一条容量b,费用a的边,每个城市到汇T建一条容量d费用-c的边

  然后每个城市再向汇T连一条容量为b,费用为-a的边(等于不卖),这样就满足最大流性质。

  然后跑一遍最小费用最大流即可。



/****************************************************

    Author : Coolxxx
    Copyright 2017 by Coolxxx. All rights reserved.
    BLOG : http://blog.csdn.net/u010568270

****************************************************/
#include<bits/stdc++.h>
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define mem(a,b) memset(a,b,sizeof(a))
const double EPS=0.00001;
const int J=10;
const int MOD=1000000007;
const int MAX=0x7f7f7f7f;
const double PI=3.14159265358979323;
const int N=504;
const int M=10004;
using namespace std;
typedef long long LL;
double anss;
LL aans;
int cas,cass;
int n,m,lll,ans;
struct xxx
{
    int next,e,q,cost;
}a[M];
int last[N],d[N],hs[N];
int S,T,nn;
bool mark[N],K;
void add(int x,int y,int z,int c)
{
    a[++lll].next=last[x];
    last[x]=lll;
    a[lll].e=y;
    a[lll].q=z;
    a[lll].cost=c;
}
void build()
{
    int i,j,k,x,y,z;
    S=n+1,T=n+2;
    nn=T;
    for(i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&x,&y,&z,&k);
        add(S,i,y,x);
        add(i,S,0,-x);
        
        add(i,T,y,-x);
        add(T,i,0,x);
        
        add(i,T,k,-z);
        add(T,i,0,z);
    }
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        
        add(x,y,MAX,z);
        add(y,x,0,-z);
        
        add(y,x,MAX,z);
        add(x,y,0,-z);
    }
}
bool spfa()
{
    int qq[M+M];
    int i,now,head,tail;
    //mem(mark,0);mem(d,0x7f);
    for(i=1;i<=nn;i++)mark[i]=0,d[i]=MAX;
    head=N;tail=N;
    qq[N]=S;
    d[S]=0;mark[S]=1;
    while(head<=tail)
    {
        now=qq[head];
        head++;
        for(i=last[now];i;i=a[i].next)
        {
            if(a[i].q>0 && d[now]+a[i].cost<d[a[i].e])
            {
                d[a[i].e]=d[now]+a[i].cost;
                if(!mark[a[i].e])
                {
                    mark[a[i].e]=1;
                    if(d[a[i].e]<d[qq[head]])
                        qq[--head]=a[i].e;
                    else
                        qq[++tail]=a[i].e;
                }
            }
        }
        mark[now]=0;
    }
    if(d[T]==MAX)return 0;
    else return 1;
}
int dfs(int u,int f)
{
    int v,i,tt,asp=0;
    if(u==T)
    {
        K=1;
        return f;
    }
    mark[u]=1;
    for(i=last[u];i;i=a[i].next)
    {
        if(!mark[a[i].e] && a[i].q>0 && d[u]+a[i].cost==d[a[i].e])
        {
            tt=dfs(a[i].e,min(a[i].q,f-asp));
            a[i].q-=tt;
            a[i^1].q+=tt;
            ans+=tt*a[i].cost;
            asp+=tt;
            if(asp==f)
                return f;
        }
    }
    return asp;
}
void mincostflow()
{
    while(1)
    {
        if(!spfa())break;
        K=1;
        while(K)
        {
            K=0;
            mem(mark,0);
            dfs(S,MAX);
        }
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.txt","r",stdin);
//    freopen("2.txt","w",stdout);
    #endif
    int i,j,k;
    int x,y,z;
//    for(scanf("%d",&cass);cass;cass--)
//    init();
//    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
    while(~scanf("%d",&n))
    {
        scanf("%d",&m);
        mem(last,0);
        lll=1;ans=0;
        build();
        mincostflow();
        cout<<-ans<<endl;
    }
    return 0;
}
/*
//

//
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值