zoukankan      html  css  js  c++  java
  • 网络流24题——负载平衡问题

    题目描述

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


    建模分析:

    首先先计算出他们的平均数,用每个数都减去平均数得到新的值,这个值如果是负数意味着需要从别的地方搞过一点来,如果正数就说明可以往外送一点.

    我们建立超级源点和超级汇点(这套路很常见的)

    如果权值为正,即储存量大于平均值,我们就从s向它连一条边,最大流为:储存值-平均值,费用为0,图论意义就是它可以从源点免费获得多出来的储存值-平均值的流量,就相当于自身有储存值-平均值的流量,上面不是说了吗,建一个超级源点,就是代替这个功能.

    如果权值为负,即储存值小于平均值,我们就从它向t连一条边,最大流量为平均值-储存值,费用为0,图论意义就是它必须从别的节点传来流量,并且汇入自身,意义类比与上面所说.

    对于每一个可以互相传的节点,即左邻居和右邻居,需要分别向他们连边,表示自己的流可以流过去.

    这是单点做法,还可以拆点,还有贪心做法,可参见均分纸牌。


    代码:

     1 #include<bits/stdc++.h>
     2 #define INF 2147483647
     3 using namespace std;
     4 queue<int> q;
     5 int n,m,len,st,ed,ans;
     6 struct node
     7 {int x,y,c,d,next;} a[10000];
     8 int b[10000],last[10000],dis[10000],pre[10000],pos[10000],p[10000];
     9 bool vis[10000];
    10 void ins(int x,int y,int c,int d)
    11 {
    12     a[len].y=y;
    13     a[len].c=c;
    14     a[len].d=d;
    15     a[len].next=last[x];
    16     last[x]=len++;
    17 }
    18 bool spfa()
    19 {
    20     memset(dis,63,sizeof(dis));
    21     memset(vis,0,sizeof(vis));
    22     vis[st]=1,dis[st]=0,q.push(st),p[st]=INF,pos[ed]=0;
    23     while (!q.empty())
    24     {
    25         int u=q.front();q.pop();
    26         vis[u]=0;
    27         for (int i=last[u];i!=-1;i=a[i].next)
    28         {
    29             int ne=a[i].y;
    30             if (a[i].c&&dis[ne]>dis[u]+a[i].d)
    31             {
    32                 dis[ne]=dis[u]+a[i].d;
    33                 pos[ne]=u;
    34                 pre[ne]=i;
    35                 p[ne]=min(p[u],a[i].c);
    36                 if (!vis[ne])
    37                 {
    38                     vis[ne]=1;
    39                     q.push(ne);
    40                 }
    41             }
    42         }
    43     }
    44     return pos[ed]!=0;
    45     //return dis[ed]<1061109567;
    46 }
    47 void dinic()
    48 {
    49     while (spfa())
    50     {
    51         ans+=p[ed]*dis[ed];
    52         for (int i=ed;i!=st;i=pos[i])
    53         {
    54             a[pre[i]].c-=p[ed];
    55             a[pre[i]^1].c+=p[ed];
    56         }
    57     }
    58 }
    59 int main()
    60 {
    61     int sum=0;
    62     scanf("%d",&n);
    63     st=0;ed=n+1;
    64     for(int i=1;i<=n;i++)
    65     {
    66         scanf("%d",&b[i]);
    67         sum+=b[i];
    68     }
    69     sum/=n;
    70     memset(last,-1,sizeof(last));
    71     for(int i=1;i<=n;i++)
    72         if(b[i]>sum)
    73             ins(st,i,b[i]-sum,0),ins(i,st,0,0);
    74         else
    75             ins(i,ed,sum-b[i],0),ins(ed,i,0,0);
    76     for(int i=2;i<=n;i++)
    77     {
    78         ins(i-1,i,INF,1),ins(i,i-1,0,-1);
    79         ins(i,i-1,INF,1),ins(i-1,i,0,-1);
    80     }
    81     ins(1,n,INF,1),ins(n,1,0,-1);
    82     ins(n,1,INF,1),ins(1,n,0,-1);
    83     dinic();
    84     printf("%d",ans);
    85 }
    View Code
  • 相关阅读:
    Redis源码分析(三十四)--- redis.h服务端的实现分析(1)
    Redis源码分析(三十四)--- redis.h服务端的实现分析(1)
    Redis源码分析(三十三)--- redis-cli.c客户端命令行接口的实现(2)
    C# 接口
    C#属性有什么作用
    字节跳动面试总结
    大厂Redis高并发场景设计,面试问的都在这!
    上班摸鱼 手敲求水仙花数的代码!
    有一群志同道合的程序员朋友是怎样的体验?
    SpringBoot四大核心之自动装配——源码解析
  • 原文地址:https://www.cnblogs.com/71-111/p/9340595.html
Copyright © 2011-2022 走看看