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
2017”百度之星”程序设计大赛 - 初赛(B)
思路:构建一个源点s和一个汇点t,生产数量和卖出数量看做cap,单价当做cost,与源点链接时费用取负,因为是生产,与汇点链接时费用取正,然后跑一下最小费用流的板子,不过要注意这里要把dis设为-inf,然后每次去最长的路,因为cost代表挣到的钱,当然是挣得越多越好,如果到汇点的路dis为负数时要跳出。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX_V = 510;
const int MAX_E = 1010;
const int INF = 0x3f3f3f3f;
struct Edge{
int to,cap,cost,rev;
};
vector<Edge> G[MAX_V];
int V,E;
void add(int u,int v,int cap,int cost){
G[u].push_back((Edge){v,cap,cost,(int)G[v].size()});
G[v].push_back((Edge){u,0,-cost,(int)G[u].size()-1});
}
int dis[MAX_V],prevv[MAX_V],preve[MAX_V];
bool used[MAX_V];
int min_cost_flow(int s,int t){
int res = 0;
while(true){
for(int i=0;i<=V+1;i++)
dis[i] = -INF;
memset(used,false,sizeof(used));
memset(prevv,-1,sizeof(prevv));
memset(preve,-1,sizeof(preve));
queue<int> q;
dis[s] = 0;
q.push(s);
used[s] = true;
while(!q.empty()){
int v = q.front();q.pop();
used[v] = false;
for(int i=0;i<G[v].size();i++){
Edge &e = G[v][i];
if(e.cap > 0 && dis[e.to] < dis[v] + e.cost){
dis[e.to] = dis[v] + e.cost;
prevv[e.to] = v;//用来记录前趋点
preve[e.to] = i;
if(!used[e.to]){
used[e.to] = true;
q.push(e.to);
}
}
}
}
if(dis[t] < 0) return res;//这里要跳出
int d = INF;
for(int v = t; v != s;v = prevv[v]){
d = min(d,G[prevv[v]][preve[v]].cap);
}//取最小的cap
res += d*dis[t];
for(int v = t;v != s;v = prevv[v]){
Edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
}
void init(){
for(int i=0;i<=V+1;i++)
G[i].clear();
}
int main(void){
while(scanf("%d %d",&V,&E) != EOF){
init();
int a,b,c,d;
int s = 0,t = V+1;
for(int i=1;i<=V;i++){
scanf("%d %d %d %d",&a,&b,&c,&d);
add(s,i,b,-a);add(i,t,d,c);
}
int x,y,z;
for(int i=1;i<=E;i++){
scanf("%d %d %d",&x,&y,&z);
add(x,y,INF,-z);
add(y,x,INF,-z);
}
int res = min_cost_flow(s,t);
printf("%d\n",res);
}
return 0;
}