1. 程式人生 > >洛谷P4016 負載平衡問題

洛谷P4016 負載平衡問題

otto stream void 後來 node inf priority prior bool

洛谷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 }

洛谷P4016 負載平衡問題