hdu 6118(最小费用流)

度度熊的交易计划

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

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
直接建图
对于每个区域i  s->i->t这样建图(双向边)
s->i的费用为a 流量为b
i->t的费用为-c  流量为d
倘若i j两点有联系的话  流量为INF 费用w
这样跑一边最小费用最大流 
在spfa算最短路里面我们需要注意的是 每一次找到一条最短路的时候 dis[t]应该是负数  否则就是亏本  亏本的肯定不能采取
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<string.h>
  7 #include<set>
  8 #include<vector>
  9 #include<queue>
 10 #include<stack>
 11 #include<map>
 12 #include<cmath>
 13 typedef long long ll;
 14 typedef unsigned long long LL;
 15 using namespace std;
 16 const double PI=acos(-1.0);
 17 const double eps=0.0000000001;
 18 const int INF=0x3f3f3f3f;
 19 const int N=10000+100;
 20 int head[N];
 21 int dis[N];
 22 int pre[N];
 23 int vis[N];
 24 int tot;
 25 int m,n;
 26 struct node{
 27     int from,to,next,flow,cost;
 28 }edge[N<<1];
 29 void init(){
 30     memset(head,-1,sizeof(head));
 31     tot=0;
 32 }
 33 void add(int u,int v,int c,int cost){
 34     edge[tot].from=u;
 35     edge[tot].to=v;
 36     edge[tot].flow=c;
 37     edge[tot].cost=cost;
 38     edge[tot].next=head[u];
 39     head[u]=tot++;
 40     edge[tot].from=v;
 41     edge[tot].to=u;
 42     edge[tot].flow=0;
 43     edge[tot].cost=-cost;
 44     edge[tot].next=head[v];
 45     head[v]=tot++;
 46 }
 47 int spfa(int s,int t){
 48     memset(pre,-1,sizeof(pre));
 49     memset(dis,INF,sizeof(dis));
 50     //cout<<dis[s]<<endl;
 51     memset(vis,0,sizeof(vis));
 52     queue<int>q;
 53     dis[s]=0;
 54     vis[s]=1;
 55     q.push(s);
 56     while(!q.empty()){
 57         int x=q.front();
 58         q.pop();
 59         vis[x]=0;
 60         for(int i=head[x];i!=-1;i=edge[i].next){
 61             int v=edge[i].to;
 62             if(edge[i].flow&&dis[v]>dis[x]+edge[i].cost){
 63                 dis[v]=edge[i].cost+dis[x];
 64                 pre[v]=i;
 65                 if(vis[v]==0){
 66                     vis[v]=1;
 67                     q.push(v);
 68                 }
 69 
 70             }
 71         }
 72     }
 73     if(dis[t]>0)return 0;
 74     return 1;
 75 }
 76 int MCMF(int s,int t){
 77     int flow=0;
 78     int cost=0;
 79     while(spfa(s,t)){
 80         int minn=INF;
 81         //cout<<3<<endl;
 82         for(int i=pre[t];i!=-1;i=pre[edge[i].from]){
 83             minn=min(minn,edge[i].flow);
 84         }
 85         for(int i=pre[t];i!=-1;i=pre[edge[i].from]){
 86             edge[i].flow=edge[i].flow-minn;
 87             edge[i^1].flow=edge[i^1].flow+minn;
 88             cost=edge[i].cost*minn+cost;
 89         }
 90         flow=flow+minn;
 91     }
 92     return -cost;
 93 }
 94 int main(){
 95     while(scanf("%d%d",&n,&m)!=EOF){
 96         init();
 97         int s=0;
 98         int t=n+100;
 99         for(int i=1;i<=n;i++){
100             int a,b,c,d;
101             scanf("%d%d%d%d",&a,&b,&c,&d);
102             add(s,i,b,a);
103             add(i,t,d,-c);
104         }
105         for(int i=1;i<=m;i++){
106             int u,v,w;
107             scanf("%d%d%d",&u,&v,&w);
108             if(u==v)continue;
109             add(u,v,INF,w);
110             add(v,u,INF,w);
111         }
112         cout<<MCMF(s,t)<<endl;
113     }
114 }

 

 

posted on 2017-08-14 22:18  见字如面  阅读(177)  评论(0编辑  收藏  举报

导航