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

P4016 负载平衡问题

题目描述

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

输入输出格式

输入格式:

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

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

 输出格式:

 输出最少搬运量。

样例输入:

5
17 9 14 16 4

样例输出:

11

模拟赛贪心水过,第一道费用流。

所有仓库的数量都相等,就应该讲多余平均值的仓库运往少于平均值的仓库,多的仓库应该贡献,连向源点;少的仓库应该得到,连向汇点,且费用为0(因为费用指在两个相邻仓库中的运输单价)。

下一步,每两个相邻的公司也需要连一条+无穷的边权,费用为1.

之后就没什么了。

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
#define N 50000
int f[N],cost[N];
int val[N],to[N],head[N],nex[N];
int a[N];
int n;
int idx=1;
int S,T;
int sum;
int ans,maxflow;
int nowflow[N];
int inq[N];
int pre[N];
void addedge(int a,int b,int c,int d)
{
    nex[++idx]=head[a];
    head[a]=idx;
    to[idx]=b;
    val[idx]=c;
    cost[idx]=d;
}
bool spfa(int S,int T)
{
    memset(f,0x3f,sizeof(f));
    memset(nowflow,0x3f,sizeof(nowflow));
    memset(inq,0,sizeof(inq));
    queue <int > q;
    f[S]=0;
    inq[S]=1;
    q.push(S);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        inq[x]=0;
        for(int i=head[x];i;i=nex[i])
        {
            if(val[i]&&f[to[i]]>f[x]+cost[i])
            {
                f[to[i]]=f[x]+cost[i];
                nowflow[to[i]]=min(nowflow[x],val[i]);
                pre[to[i]]=i;
                if(!inq[to[i]])
                {
                    inq[to[i]]=1;
                    q.push(to[i]);
                }
            }
        }
    }
    if(f[T]>=0x3f3f3f3f)
        return 0;
    return 1;
}
void EK()
{
    int x=T;
    while(x!=S)
    {
        int i=pre[x];
        val[i]-=nowflow[T];
        val[i^1]+=nowflow[T];
        x=to[i^1];
    }
    maxflow+=nowflow[T];
    ans+=f[T]*nowflow[T];
}
int main()
{
    scanf("%d",&n);
    S=0,T=n+1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    sum/=n;
    for(int i=1;i<=n;i++)
    {
        if(sum>a[i])
        {
            addedge(S,i,sum-a[i],0);
            addedge(i,S,0,0);
        }
        else
        {
            addedge(i,T,a[i]-sum,0);
            addedge(T,i,0,0);
        }
    }
    for(int i=2;i<=n;i++)
    {
        addedge(i-1,i,1<<30,1);
        addedge(i,i-1,0,-1);
        addedge(i,i-1,1<<30,1);
        addedge(i-1,i,0,-1);
    }
    addedge(n,1,1<<30,1);
    addedge(1,n,0,-1);
    addedge(1,n,1<<30,1);
    addedge(n,1,0,-1);
    while(spfa(S,T))
        EK();
    printf("%d",ans);
}

猜你喜欢

转载自www.cnblogs.com/342zhuyongqi/p/9830773.html
今日推荐