(最小费用流)hdu 6118(2017百度之星初赛B 1005) 度度熊的交易计划

Posted 惜取少年时

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(最小费用流)hdu 6118(2017百度之星初赛B 1005) 度度熊的交易计划相关的知识,希望对你有一定的参考价值。

度度熊的交易计划

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


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

 

恰当的建图之后就是个裸的最小费用流(当然,由于求的是最大盈利,值乘-1进行计算)了。将每个点拆成3个,分别为: 由源点连向的点(边cost=a[i],cap=b[i]) 由第一种点(对应原图中下标设为i)连向的“入点”(对应原图中下标设为j)(cost=-(c[j]-dis[i][j]),cap=a[i])(其中dis[i][j]为i到j的最短路,事先需要floyd跑一边求一下) 由于每个点出售的数量是有限制的,故第三种点为第二种点一一对应连接的(cost=0,cap=d[i])第三种点再连向汇点。

不过需要注意的是,这样建的图并不一定是满流(因为有的地方可以不生产),故为了保证最小费用流中的满流条件,再增加一个“超级源点”、“超级汇点”,分别与原本的源点、汇点相连,并增加一条从原本的源点连向汇点的cost=0,cap=INF的边。

建完图之后直接进行最小费用流即可。

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <set>
  6 #include <map>
  7 #include <string>
  8 #include <cstring>
  9 #include <stack>
 10 #include <queue>
 11 #include <cmath>
 12 #include <ctime>
 13 #include<bitset>
 14 #include <utility>
 15 using namespace std;
 16 #define REP(I,N) for (I=0;I<N;I++)
 17 #define rREP(I,N) for (I=N-1;I>=0;I--)
 18 #define rep(I,S,N) for (I=S;I<N;I++)
 19 #define rrep(I,S,N) for (I=N-1;I>=S;I--)
 20 #define FOR(I,S,N) for (I=S;I<=N;I++)
 21 #define rFOR(I,S,N) for (I=N;I>=S;I--)
 22 #define rank rankk
 23 #define DFT FFT
 24 typedef unsigned long long ull;
 25 typedef long long ll;
 26 //const int INF=0x3f3f3f3f;
 27 const ll INFF=0x3f3f3f3f3f3f3f3fll;
 28 //const ll M=1e9+7;
 29 const ll maxn=2e5+7;
 30 //const int MAXN=1005;
 31 const int MAX=1e6+5;
 32 const int MAX_N=MAX;
 33 //const int N=55;
 34 const ll MOD=1e9+7;
 35 //const double eps=0.00000001;
 36 int gcd(int a,int b){return b?gcd(b,a%b):a;}
 37 template<typename T>inline T abs(T a) {return a>0?a:-a;}
 38 inline ll powMM(ll a,ll b,ll M){
 39     ll ret=1;
 40     a%=M;
 41 //    b%=M;
 42     while (b){
 43         if (b&1) ret=ret*a%M;
 44         b>>=1;
 45         a=a*a%M;
 46     }
 47     return ret;
 48 }
 49 void open()
 50 {
 51     freopen("t.txt","r",stdin);
 52     freopen("out.txt","w",stdout);
 53 }
 54 
 55 const int MAXN = 10000;
 56 const int MAXM = 1000000;
 57 const int INF = 0x3f3f3f3f;
 58 struct Edge
 59 {
 60 int to,next,cap,flow,cost;
 61 }edge[MAXM];
 62 int head[MAXN],tol;
 63 int pre[MAXN],dis[MAXN];
 64 bool vis[MAXN];
 65 int N;//节点总个数,节点编号从0~N-1
 66 void init(int n)
 67 {
 68 N = n;
 69 tol = 0;
 70 memset(head,-1,sizeof(head));
 71 }
 72 void addedge(int u,int v,int cap,int cost)
 73 {
 74 edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;
 75 }
 76 bool spfa(int s,int t)
 77 {
 78 queue<int>q;
 79 for(int i = 0;i < N;i++)
 80 {
 81 dis[i] = INF; vis[i] = false; pre[i] = -1;
 82 }
 83 dis[s] = 0; vis[s] = true; q.push(s); while(!q.empty())
 84 {
 85 int u = q.front(); q.pop();
 86 vis[u] = false;
 87 for(int i = head[u]; i != -1;i = edge[i].next)
 88 {
 89 int v = edge[i].to;
 90 
 91 
 92 if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost )
 93 {
 94 dis[v] = dis[u] + edge[i].cost; pre[v] = i;
 95 if(!vis[v])
 96 {
 97 vis[v] = true; q.push(v);
 98 }
 99 }
100 }
101 }
102 if(pre[t] == -1)return false; else return true;
103 }
104 //返回的是最大流,cost存的是最小费用
105 int minCostMaxflow(int s,int t,int &cost)
106 {
107 int flow = 0; cost = 0; while(spfa(s,t))
108 {
109 int Min = INF;
110 for(int i = pre[t];i != -1;i = pre[edge[i^1].to])
111 {
112 if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow;
113 }
114 for(int i = pre[t];i != -1;i = pre[edge[i^1].to])
115 {
116 edge[i].flow += Min; edge[i^1].flow -= Min;
117 cost += edge[i].cost * Min;
118 }
119 flow += Min;
120 }
121 return flow;
122 }
123 int n,m;
124 int diss[505][505];
125 int a[505],b[505],c[505],d[505];
126 int V;//顶点数
127 void warshall_floyd()
128 {
129     for(int k=1;k<=V;k++)
130         for(int i=1;i<=V;i++)
131             for(int j=1;j<=V;j++)
132                 diss[i][j]=min(diss[i][j],diss[i][k]+diss[k][j]);
133 }
134 int main()
135 {
136     while(~scanf("%d%d",&n,&m))
137     {
138         memset(diss,-1,sizeof(diss));
139         for(int i=1;i<=n;i++)
140             scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
141         for(int i=1;i<=n;i++)
142             for(int j=1;j<=n;j++)
143                 diss[i][j]=(int)1e9;
144         for(int i=1;i<=n;i++)
145             diss[i][i]=0;
146         for(int i=1;i<=m;i++)
147         {
148             int x,y,z;
149             scanf("%d%d%d",&x,&y,&z);
150             if(x==y)
151                 continue;
152             diss[x][y]=diss[y][x]=min(z,diss[x][y]);
153         }
154         V=n;
155         warshall_floyd();
156         init(3*n+4);
157         for(int i=1;i<=n;i++)
158             addedge(0,i,b[i],a[i]);
159         for(int i=1;i<=n;i++)
160         {
161             for(int j=1;j<=n;j++)
162             {
163                 if(diss[i][j]!=-1&&c[j]>=a[i]+diss[i][j])
164                     addedge(i,j+n,b[i],-(c[j]-diss[i][j]));
165             }
166         }
167         for(int i=1;i<=n;i++)
168             addedge(i+n,i+2*n,d[i],0);
169         for(int i=1;i<=n;i++)
170             addedge(i+2*n,3*n+1,d[i],0);
171         addedge(3*n+2,0,INF,0);
172         addedge(3*n+1,3*n+3,INF,0);
173         addedge(0,3*n+1,INF,0);
174         int co;
175         int an=minCostMaxflow(3*n+2,3*n+3,co);
176         printf("%d\n",-co);
177     }
178 }

 

以上是关于(最小费用流)hdu 6118(2017百度之星初赛B 1005) 度度熊的交易计划的主要内容,如果未能解决你的问题,请参考以下文章

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

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

HDU 6118 度度熊的交易计划 最大费用可行流

[HDOJ6118] 度度熊的交易计划(最小费用可行流)

百度之星初赛B轮 hdu 6114 6118 6119

HDU 6188最小费用流