网络流24题之负载平衡问题

这就是均分纸牌加强版,不过我们要用网络流做。

看了一下hzwer博客深受启发。

「问题分析」

转化为供求平衡问题,用最小费用最大流解决。

「建模方法」

首先求出所有仓库存货量平均值,设第i个仓库的盈余量为A[i],A[i] = 第i个仓库原有存货量 – 平均存货量。建立二分图,把每个仓库抽象为两个节点Xi和Yi。增设附加源S汇T。

1、如果A[i]>0,从S向Xi连一条容量为A[i],费用为0的有向边。
2、如果A[i]<0,从Yi向T连一条容量为-A[i],费用为0的有向边。
3、每个Xi向两个相邻顶点j,从Xi到Xj连接一条容量为无穷大,费用为1的有向边,从Xi到Yj连接一条容量为无穷大,费用为1的有向边。

求最小费用最大流,最小费用流值就是最少搬运量。

「建模分析」

计算出每个仓库的盈余后,可以把问题转化为供求问题。建立供求网络,把二分图X集合中所有节点看做供应节点,Y集合所有节点看做需求节点,在能一次搬运满足供需的Xi和Yj之间连接一条费用为1的有向边,表示搬运一个单位货物费用为1。另外还要在Xi与相邻的Xj之间连接边,表示货物可以暂时搬运过去,不立即满足需求,费用也为1。最大流满足了所有的盈余和亏损供求平衡,最小费用就是最少搬运量。

很好写了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=250005,inf=1e9;
 4 int d[N],head[N],cnt=-1,n,a[N],cost,f[N],s,t;
 5 bool v[N];
 6 struct node{
 7     int w,to,nex,c,f;
 8 }e[1000005];
 9 void add(int x,int y,int w,int c)
10 {
11     e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;e[cnt].f=x;e[cnt].w=w;e[cnt].c=c;
12     e[++cnt].to=x;e[cnt].nex=head[y];head[y]=cnt;e[cnt].f=y;e[cnt].w=0;e[cnt].c=-c;
13 }
14 queue<int>q;
15 bool spfa()
16 {
17     memset(d,0x3f,sizeof(d));
18     memset(v,0,sizeof(v));
19     memset(f,-1,sizeof(f));
20     v[s]=1;d[s]=0;q.push(s);
21     while(!q.empty())
22     {
23         int x=q.front();q.pop();v[x]=0;
24         for(int i=head[x];i!=-1;i=e[i].nex)
25         {
26             if(!e[i].w||d[e[i].to]<=d[x]+e[i].c)continue;
27             int y=e[i].to;
28             d[y]=d[x]+e[i].c;f[y]=i;
29             if(!v[y])
30             {
31                 q.push(y);v[y]=1;
32             }
33         }
34     }
35     if(d[t]>inf)return 0;
36     int flow=inf;
37     for(int i=f[t];i!=-1;i=f[e[i].f])
38     flow=min(flow,e[i].w);
39     for(int i=f[t];i!=-1;i=f[e[i].f])
40     e[i].w-=flow,e[i^1].w+=flow,cost+=flow*e[i].c;
41     return 1;
42 }
43 int main()
44 {
45     scanf("%d",&n);int sum=0;memset(head,-1,sizeof(head));
46     for(int i=1;i<=n;++i)scanf("%d",&a[i]),sum+=a[i];
47     int ave=sum/n;t=(n<<1)+10;s=0;
48     for(int i=1;i<=n;++i)a[i]=a[i]-ave;
49     for(int i=1;i<=n;++i)
50     {
51         int x=(i==1)?n:i-1;int y=(i==n)?1:i+1;
52         if(a[i]<0)add(i<<1|1,t,-a[i],0);
53         else add(s,i<<1,a[i],0);
54         add(i<<1,x<<1,inf,1);add(i<<1,y<<1,inf,1);
55         add(i<<1,(x<<1)|1,inf,1);add(i<<1,(y<<1)|1,inf,1);
56     }
57     while(spfa());
58     printf("%d\n",cost);
59     return 0;
60 }

 

posted @ 2018-02-04 16:13  大奕哥&VANE  阅读(196)  评论(0编辑  收藏  举报