LuoguP4016 负载平衡问题(费用流)

题目描述

G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 n 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。

输入输出格式

输入格式:

文件的第 11 行中有 11 个正整数 n,表示有 n 个仓库。

第 22 行中有 n 个正整数,表示 n 个仓库的库存量。

输出格式:

输出最少搬运量。

解题思路:

因为已知了最终状态,相当于已知每个点的搬运数量。

现在就是令搬运次数尽量少。

相当于每个点与相邻点连inf的边费用为1

大于平均值与汇点连流量为增量边费用为0

源点与小于平均值连流量为增量边费用为0

跑费用流就好了。

代码:

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 const int oo=0x7f7f7f7f;
  6 struct pnt{
  7     int hd;
  8     int val;
  9     int dis;
 10     int pre;
 11     int lst;
 12     bool vis;
 13 }p[1001];
 14 struct ent{
 15     int twd;
 16     int lst;
 17     int vls;
 18     int cst;
 19 }e[100000];
 20 int cnt;
 21 int n,m;
 22 int s,t;
 23 int a[10000];
 24 std::queue<int>Q;
 25 void ade(int f,int t,int mf,int ct)
 26 {
 27     cnt++;
 28     e[cnt].twd=t;
 29     e[cnt].lst=p[f].hd;
 30     e[cnt].vls=mf;
 31     e[cnt].cst=ct;
 32     p[f].hd=cnt;
 33     return ;
 34 }
 35 bool Spfa(void)
 36 {
 37     while(!Q.empty())
 38         Q.pop();
 39     for(int i=1;i<=n+2;i++)
 40     {
 41         p[i].val=0x3f3f3f3f;
 42         p[i].dis=0x3f3f3f3f;
 43         p[i].vis=false;
 44     }
 45     p[s].dis=0;
 46     p[s].vis=true;
 47     p[t].pre=-1;
 48     Q.push(s);
 49     while(!Q.empty())
 50     {
 51         int x=Q.front();
 52         Q.pop();
 53         p[x].vis=false;
 54         for(int i=p[x].hd;i;i=e[i].lst)
 55         {
 56             int to=e[i].twd;
 57             if(e[i].vls>0&&p[to].dis>p[x].dis+e[i].cst)
 58             {
 59                 p[to].dis=p[x].dis+e[i].cst;
 60                 p[to].val=std::min(p[x].val,e[i].vls);
 61                 p[to].pre=x;
 62                 p[to].lst=i;
 63                 if(!p[to].vis)
 64                 {
 65                     p[to].vis=true;
 66                     Q.push(to);
 67                 }
 68             }
 69         }
 70     }
 71     return p[t].pre!=-1;
 72 }
 73 int Ek(void)
 74 {
 75     int ret=0;
 76     while(Spfa())
 77     {
 78         ret+=p[t].dis*p[t].val;
 79         for(int i=t;i!=s;i=p[i].pre)
 80         {
 81             e[p[i].lst].vls-=p[t].val;
 82             e[((p[i].lst-1)^1)+1].vls+=p[t].val;
 83         }
 84     }
 85     return ret;
 86 }
 87 int main()
 88 {
 89 //    freopen("a.in","r",stdin);
 90     int sum=0;
 91     scanf("%d",&n);
 92     for(int i=1;i<=n;i++)
 93     {
 94         scanf("%d",&a[i]);
 95         sum+=a[i];
 96     }
 97     s=n+1,t=n+2;
 98     sum/=n;
 99     for(int i=1;i<=n;i++)
100     {
101         if(a[i]>sum)
102         {
103             ade(s,i,a[i]-sum,0);
104             ade(i,s,0,0);
105         }else{
106             ade(i,t,sum-a[i],0);
107             ade(t,i,0,0);
108         }
109     }
110     for(int i=1;i<n;i++)
111     {
112         ade(i,i+1,oo,1);ade(i+1,i,0,-1);
113         ade(i+1,i,oo,1);ade(i,i+1,0,-1);
114     }
115     ade(1,n,oo,1);ade(n,1,0,-1);
116     ade(n,1,oo,1);ade(1,n,0,-1);
117     printf("%d\n",Ek());
118     return 0;
119 }

 

posted @ 2019-01-01 16:47  Unstoppable728  阅读(172)  评论(0编辑  收藏  举报