[题解]P4016|负载平衡问题

负载平衡问题

题目链接

(下文中\(x\xrightarrow{a,b}y\)表示从\(x\)\(y\)连一条流量为\(a\),费用为\(b\)的边)

在做均分纸牌那题的时候,我们首先求出了牌数的平均值,对与每一堆牌减平均值

这道题同理,

1.货物数减去 \(arv\) 若大于0

\(s \xrightarrow{a[i]-arv,0}i\)

表示 \(i\) 可以获得数量为 \(a[i]-arv\) 的货物

2.货物数减去 \(arv\) 若小于0

\(i \xrightarrow{arv-a[i],0}i\)

表示 \(i\) 可以流出数量为 \(arv-a[i]\) 的货物

3. 向旁边的两个仓库连边:

\(i\xrightarrow{+\infty,1}i+1,i\xrightarrow{+\infty,1}i-1\)

表示 \(i\) 可以将货物流向 \(i+1,i-1\)

坠后从\(s\)\(t\)跑最小费用最大流即可


\(\mathcal{Code}:\)

#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 575
#define inf 2147483647
#define int long long
#define debug cout<<__LINE__<<" "<<__FUNCTION__<<"\n"
inline int read(){
	int x=0,y=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')y=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*y;
}
struct Edge{
    int to,flow,cost,nxt;
}edge[N];
int n,m,s,t,tot=1;
int flow[N],deep[N],last[N],pre[N],vis[N],head[N],a[N];//pre: point   last:edge
int maxflow,mincost;
inline void add(int from,int to,int flow,int cost){
    edge[++tot].nxt=head[from];
    edge[tot].to=to;
    edge[tot].flow=flow;
    edge[tot].cost=cost;
    head[from]=tot;
}
bool spfa(){
    memset(flow,0x3f,sizeof(flow));
    memset(deep,0x3f,sizeof(deep));
    memset(vis,0,sizeof(vis));
    deep[s]=0;
    pre[t]=-1;
    vis[s]=1;
    queue<int>q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u] = 0;
        for(int i = head[u];i;i = edge[i].nxt){
            int v = edge[i].to;
            if(deep[v] > deep[u] + edge[i].cost && edge[i].flow){
                flow[v] = min(flow[u],edge[i].flow);
                deep[v] = deep[u] + edge[i].cost;
                pre[v] = u;last[v] = i;
                if(!vis[v]){
                    vis[v] = 1;q.push(v);
                }
            }
        }
    }
    return pre[t]!=-1;
}
inline void Dinic(){
    while(spfa()){
        maxflow += flow[t];
        mincost += flow[t] * deep[t];
        int x = t;
        while(x != s){
            edge[last[x]].flow -= flow[t];
            edge[last[x] ^ 1].flow += flow[t];
            x = pre[x];
        }
    }
}
signed main(){
//	freopen("a.in","r",stdin);
//	freopen(".out","w",stdout);
	n=read();
	s=0;t=n+1;
	int sum=0;
	for(int i=1;i<=n;i++){
		a[i]=read();sum+=a[i];
	}
	sum/=n;
	for(int i=1;i<=n;i++){
		a[i]-=sum;
		if(a[i]>0) add(s,i,a[i],0),add(i,s,0,0);
		if(a[i]<0) add(i,t,-a[i],0),add(t,i,0,0);
	}
	for(int i=1;i<=n;i++){
		add(i,i%n+1,inf,1);add(i%n+1,i,0,-1);
		add(i,(i-2+n)%n+1,inf,1);add((i-2+n)%n+1,i,0,-1);
	}
	Dinic();
	cout<<mincost<<"\n";
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}
posted @ 2019-09-17 17:22  zh_dou  阅读(111)  评论(0编辑  收藏  举报