HDU 6118 度度熊的交易计划(最小费用最大流)

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

题意

如上

题解

超级源点S=0,超级汇点T=n+1

对于每个a,b,c,d

建图从源点到i建边,流量为b花费为a,从i到汇点建边,流量为d花费为-c

最后每个u,v建边,流量INF,花费dis

跑一个S到T的最小费用最大流,由于每个花费都取反了,所以跑出来的值就是最大费用最大流

这里有个坑点是如果源点到汇点的距离DIST[T]>0说明以后的增广路都是亏钱,就可以直接跳出循环

代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int N=1e5+5;
  5 const int M=2e5+5;
  6 const int INF=0x3f3f3f3f;
  7 
  8 int FIR[N],FROM[M],TO[M],CAP[M],FLOW[M],COST[M],NEXT[M],tote;
  9 int pre[N],dist[N],q[400000];
 10 bool vis[N];
 11 int n,m,S,T;
 12 void init()
 13 {
 14     tote=0;
 15     memset(FIR,-1,sizeof(FIR));
 16 }
 17 void addEdge(int u,int v,int cap,int cost)
 18 {
 19     FROM[tote]=u;
 20     TO[tote]=v;
 21     CAP[tote]=cap;
 22     FLOW[tote]=0;
 23     COST[tote]=cost;
 24     NEXT[tote]=FIR[u];
 25     FIR[u]=tote++;
 26 
 27     FROM[tote]=v;
 28     TO[tote]=u;
 29     CAP[tote]=0;
 30     FLOW[tote]=0;
 31     COST[tote]=-cost;
 32     NEXT[tote]=FIR[v];
 33     FIR[v]=tote++;
 34 }
 35 bool SPFA(int s, int t)
 36 {
 37     memset(dist,INF,sizeof(dist));
 38     memset(vis,false,sizeof(vis));
 39     memset(pre,-1,sizeof(pre));
 40     dist[s] = 0;vis[s]=true;q[1]=s;
 41     int head=0,tail=1;
 42     while(head!=tail)
 43     {
 44         int u=q[++head];vis[u]=false;
 45         for(int v=FIR[u];v!=-1;v=NEXT[v])
 46         {
 47             if(dist[TO[v]]>dist[u]+COST[v]&&CAP[v]>FLOW[v])
 48             {
 49                 dist[TO[v]]=dist[u]+COST[v];
 50                 pre[TO[v]]=v;
 51                 if(!vis[TO[v]])
 52                 {
 53                     vis[TO[v]] = true;
 54                     q[++tail]=TO[v];
 55                 }
 56             }
 57         }
 58     }
 59     if(dist[t]>0)return false;//亏钱
 60     return pre[t]!=-1;
 61 }
 62 void MCMF(int s, int t, int &cost, int &flow)
 63 {
 64     flow=0;
 65     cost=0;
 66     while(SPFA(s,t))
 67     {
 68         int Min = INF;
 69         for(int v=pre[t];v!=-1;v=pre[TO[v^1]])
 70             Min = min(Min, CAP[v]-FLOW[v]);
 71         for(int v=pre[t];v!=-1;v=pre[TO[v^1]])
 72         {
 73             FLOW[v]+=Min;
 74             FLOW[v^1]-=Min;
 75             cost+=COST[v]*Min;
 76         }
 77         flow+=Min;
 78     }
 79 }
 80 int main()
 81 {
 82     while(scanf("%d%d",&n,&m)!= EOF)
 83     {
 84         init();
 85         S=0,T=n+1;
 86         int u,v,a,b,c,d;
 87         for(int i=1;i<=n;i++)
 88         {
 89             scanf("%d%d%d%d",&a,&b,&c,&d);
 90             addEdge(S,i,b,a);
 91             addEdge(i,T,d,-c);
 92         }
 93         for(int i=1;i<=m;i++)
 94         {
 95             scanf("%d%d%d",&u,&v,&d);
 96             addEdge(u,v,0x3f3f3f3f,d);
 97             addEdge(v,u,0x3f3f3f3f,d);
 98         }
 99         int cost,flow;
100         MCMF(S,T,cost,flow);
101         printf("%d\n",-cost);
102     }
103     return 0;
104 }

 

posted on 2018-09-19 15:29  大桃桃  阅读(152)  评论(0)    收藏  举报

导航