• [网络流24题] 负载平衡问题 (费用流)


    洛谷传送门 LOJ传送门

    本题解思路来自hzwer黄学长

    搬运后每个位置应该有的货物数量$num=frac{sum a_{i}}{n}$

    那么大于$num$的位置都应该把一部分货物提供给其他位置,反之是被提供货物

    把源点和汇点想象成货物中心

    那么源点向$a_{i}>num$的位置连一条流量为$a_{i}-num$,长度是$0$的边

    向$a_{i}<num$的位置向汇点连一条流量为$num-a_{i}$,长度是$0$的边

    而相邻的货物间可以随便运货,故连一条流量是$inf$,长度是$1$的边,注意货物的是一个环

    源点向汇点的一条可行流可以理解成,连接源点的那个点 贡献出$flow$数量的货物,长途跋涉,到达连接汇点的那个点

    我们的目的是保证每个位置多出来的货物全部运给少的,而这个图的最大流其实就是把连接源点的边全都跑满

    我们要求的是最少花费,跑最小费用最大流就行了

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N1 105
     6 #define M1 50010
     7 #define ll long long
     8 #define dd double
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 
    12 int gint()
    13 {
    14     int ret=0,fh=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    17     return ret*fh;
    18 }
    19 
    20 int n,m,S,T;
    21 struct Edge{
    22 int head[N1],to[M1<<1],nxt[M1<<1],dis[M1<<1],flow[M1<<1],cte;
    23 void ae(int u,int v,int F,int W)
    24 {
    25     cte++; to[cte]=v; flow[cte]=F; dis[cte]=W; 
    26     nxt[cte]=head[u]; head[u]=cte;
    27 }
    28 }e;
    29 
    30 int que[M1<<1],dis[N1],flow[N1],use[N1],id[N1],hd,tl;
    31 int spfa()
    32 {
    33     int x,j,v;
    34     memset(dis,0x3f,sizeof(dis)); memset(use,0,sizeof(use)); memset(flow,0,sizeof(flow));
    35     hd=1,tl=0; que[++tl]=S; dis[S]=0; flow[S]=inf; use[S]=1;
    36     while(hd<=tl)
    37     {
    38         x=que[hd++];
    39         for(j=e.head[x];j;j=e.nxt[j])
    40         {
    41             v=e.to[j]; 
    42             if( e.flow[j]>0 && dis[v]>dis[x]+e.dis[j] )
    43             {
    44                 dis[v]=dis[x]+e.dis[j]; id[v]=j;
    45                 flow[v]=min(flow[x],e.flow[j]);
    46                 if(!use[v]) que[++tl]=v, use[v]=1;
    47             }
    48         }
    49         use[x]=0;
    50     }
    51     return dis[T]!=inf;
    52 }
    53 
    54 int mxflow,cost;
    55 int EK()
    56 {
    57     int x;
    58     while(spfa())
    59     {
    60         for(x=T;x!=S;x=e.to[id[x]^1])
    61         {
    62             e.flow[id[x]]-=flow[T];
    63             e.flow[id[x]^1]+=flow[T];
    64         }
    65         mxflow+=flow[T]; cost+=flow[T]*dis[T];
    66     }
    67     return cost;
    68 }
    69 
    70 int a[N1];
    71 
    72 int main()
    73 {
    74     scanf("%d",&n);
    75     int i,x,y,z,sum=0; e.cte=1; S=n+1,T=n+2;
    76     for(i=1;i<=n;i++) scanf("%d",&a[i]), sum+=a[i]; sum/=n;
    77     for(i=1;i<=n;i++)
    78         if(a[i]>sum) e.ae(S,i,a[i]-sum,0), e.ae(i,S,0,0);
    79         else if(a[i]<sum) e.ae(i,T,sum-a[i],0), e.ae(T,i,0,0);
    80     for(i=1;i<n;i++) e.ae(i,i+1,inf,1), e.ae(i+1,i,0,-1); e.ae(n,1,inf,1), e.ae(1,n,0,-1);
    81     for(i=2;i<=n;i++) e.ae(i,i-1,inf,1), e.ae(i-1,i,0,-1); e.ae(1,n,inf,1), e.ae(n,1,0,-1);
    82     printf("%d
    ",EK());
    83     //for(i=1,num=0;i<=n;i++) num+=abs(a[i]-sum);
    84     return 0;
    85 }
  • 相关阅读:
    4.2网络层提供的两种服务
    4.1网络层概述
    MATLAB曲面插值及交叉验证
    python爬虫成长之路(二):抓取代理IP并多线程验证
    KNN识别图像上的数字及python实现
    python爬虫成长之路(一):抓取证券之星的股票数据
    YARN环境搭建 之 一:CentOS7.0系统配置
    高效学习方法总结
    《立委随笔:机器学习和自然语言处理》
    XenServer安装虚拟机先扩容存放ISO镜像文件
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10281864.html
Copyright © 2020-2023  润新知