HDU6118:度度熊的交易计划(入门级最小费用可行流)
度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题:
喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区。
由于生产能力的区别,第i个片区能够花费a[i]元生产1个商品,但是最多生产b[i]个。
同样的,由于每个片区的购买能力的区别,第i个片区也能够以c[i]的价格出售最多d[i]个物品。
由于这些因素,度度熊觉得只有合理的调动物品,才能获得最大的利益。
据测算,每一个商品运输1公里,将会花费1元。
那么喵哈哈村最多能够实现多少盈利呢?
喵哈哈村以及周围的村庄可以看做是一共由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
思路:建图,每次spfa完,如果dis[S]<0,说明有收益,累加即可,否则退出。
#include<bits/stdc++.h> const int inf=1<<30; const int maxn=1010; using namespace std; int To[maxn*6],Laxt[maxn],Next[maxn*6],cap[maxn*6],cost[maxn*6]; int S,T,cnt=1,dis[maxn],ans; bool inq[maxn],vis[maxn]; deque<int>q; void add(int u,int v,int c,int cc) { Next[++cnt]=Laxt[u];Laxt[u]=cnt; To[cnt]=v;cap[cnt]=c;cost[cnt]=cc; } bool spfa() { for(int i=0;i<=T;i++) inq[i]=0; for(int i=0;i<=T;i++) dis[i]=inf; inq[T]=1; dis[T]=0; q.push_back(T); while(!q.empty()) { int u=q.front(); q.pop_front(); inq[u]=0; for(int i=Laxt[u];i;i=Next[i]) { int v=To[i]; if(cap[i^1]&&dis[v]>dis[u]-cost[i]) { dis[v]=dis[u]-cost[i]; if(!inq[u]){ inq[v]=1; if(q.empty()||dis[v]>dis[q.front()]) q.push_back(v); else q.push_front(v); } } } } return dis[S]<inf; } int dfs(int u,int flow) { vis[u]=1; if(u==T||flow==0) return flow; int tmp,delta=0; for(int i=Laxt[u];i;i=Next[i]) { int v=To[i]; if((!vis[v])&&cap[i]&&dis[v]==dis[u]-cost[i]) { tmp=dfs(v,min(cap[i],flow-delta)); delta+=tmp; cap[i]-=tmp; cap[i^1]+=tmp; } } return delta; } int main() { int N,M,a,b,c,d,u,v,w,i; while(~scanf("%d%d",&N,&M)){ S=0; T=N+1; cnt=1; ans=0; for(i=0;i<=T;i++) Laxt[i]=0; for(i=1;i<=N;i++){ scanf("%d%d%d%d",&a,&b,&c,&d); add(S,i,b,a); add(i,S,0,-a); add(i,T,d,-c); add(T,i,0,c); } for(i=1;i<=M;i++){ scanf("%d%d%d",&u,&v,&w); add(u,v,inf,w); add(v,u,0,-w); add(v,u,inf,w); add(u,v,0,-w); } while(spfa()){ if(dis[S]>0) break; vis[T]=1; while(vis[T]){ for(i=0;i<=T;i++) vis[i]=0; ans-=dis[S]*dfs(S,inf); } } printf("%d\n",ans); } return 0; }
It is your time to fight!