洛谷P4016 负载平衡问题
题目大意:
G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 n 个仓库的库存数量相同。搬运货物时,只
能在相邻的仓库之间搬运。
思路:
最小费用最大流。
假设物品的总库存之和为sum,那么为了使库存之和相等,搬运结束后每一个仓库的目标库存量ave应该都等于sum/n。
这时候很显然,我们发现初始库存量>ave的仓库会向其他仓库搬运货物,而初始库存量<ave的仓库会接收货物。
所以我们将所有仓库的初始货物数nums[i]减去ave,如果nums[i]-ave>0,那么由超级源点向他发出一条流量为nums[i]-ave,费用为0的边。
如果nums[i]-ave<0,那么由他向超级汇点发出一条流量为ave-nums[i],费用为0的边。
最后再在所有相邻的仓库之间互相建立流量为无穷大,费用为1的双向边。
然后就没有然后了。。。
我的错误o(╥﹏╥)o
1、一开始直接跑了最大流,结果WA了9个点,后来发现最大流无法计算转移量之和,其实这是一个很蠢的错误、、、
2、加双向边的时候有一个细节,因为我用的是邻接表,一开始加双向边的时候没有加入费用为负的辅助边,结果还是WA了9个点。。。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 #define MAXN 110 8 struct Node{ 9 int u,v,w,c; 10 Node(){} 11 Node(int u,int v,int w,int c):u(u),v(v),w(w),c(c){} 12 }p[MAXN<<3]; 13 struct Record{ 14 int u,dis; 15 Record(){} 16 Record(int u,int dis):u(u),dis(dis){} 17 bool operator < (const Record & a) const{ 18 return dis>a.dis; 19 } 20 }; 21 int head[MAXN],Next[MAXN<<3],nums[MAXN],dis[MAXN],pre[MAXN],preNode[MAXN]; 22 bool vis[MAXN]; 23 int i,j,k,m,n,tot,sum; 24 void addNode(int u,int v,int w,int c){ 25 p[++tot]=Node(u,v,w,c); 26 Next[tot]=head[u],head[u]=tot; 27 p[++tot]=Node(v,u,0,-c); 28 Next[tot]=head[v],head[v]=tot; 29 } 30 bool dijkstra(int src,int goal){ 31 priority_queue<Record> mque; 32 while(!mque.empty()) mque.pop(); 33 for(register int i=0;i<=n+1;i++) vis[i]=false,dis[i]=1000000000; 34 mque.push(Record(src,0)); 35 vis[src]=true; dis[src]=0; 36 pre[src]=-1; 37 while(!mque.empty()){ 38 Record tmp=mque.top(); mque.pop(); 39 if(dis[tmp.u]<tmp.dis) continue; 40 //if(vis[tmp.u]) continue; 41 for(register int i=head[tmp.u];i+1;i=Next[i]){ 42 if(p[i].w&&dis[tmp.u]+p[i].c<dis[p[i].v]){ 43 pre[p[i].v]=tmp.u; 44 preNode[p[i].v]=i; 45 dis[p[i].v]=dis[tmp.u]+p[i].c; 46 mque.push(Record(p[i].v,dis[p[i].v])); 47 } 48 } 49 } 50 if(dis[goal]!=1000000000) return true; 51 return false; 52 } 53 int dinic(int src,int goal){ 54 int ans=0; 55 while(dijkstra(src,goal)){ 56 int minf=1000000000; 57 for(register int i=goal;i!=src;i=pre[i]){ 58 minf=min(minf,p[preNode[i]].w); 59 } 60 for(register int i=goal;i!=src;i=pre[i]){ 61 p[preNode[i]].w-=minf; 62 p[preNode[i]^1].w+=minf; 63 } 64 ans+=dis[goal]*minf; 65 } 66 return ans; 67 } 68 int main(){ 69 scanf("%d",&n); 70 sum=0; 71 for(i=1;i<=n;i++) scanf("%d",nums+i),sum+=nums[i]; 72 sum/=n; 73 for(i=0;i<=n+1;i++) head[i]=-1; 74 tot=-1; 75 for(i=1;i<=n;i++) nums[i]-=sum; 76 for(i=1;i<=n;i++) if(nums[i]>0) addNode(0,i,nums[i],0); else { if(nums[i]<0) addNode(i,n+1,-nums[i],0); } 77 for(i=1;i<=n-1;i++) addNode(i,i+1,10000000,1),addNode(i+1,i,10000000,1); 78 addNode(n,1,10000000,1),addNode(1,n,10000000,1); 79 printf("%d\n",dinic(0,n+1)); 80 return 0; 81 }
原文:https://www.cnblogs.com/linxif2008/p/9532392.html