【網絡流24題-洛谷-P4016】負載平衡問題(最小代價供求、最小費用最大流)

題目描述

GG 公司有 nn 個沿鐵路運輸線環形排列的倉庫,每個倉庫存儲的貨物數量不等。如何用最少搬運量可以使 nn 個倉庫的庫存數量相同。搬運貨物時,只能在相鄰的倉庫之間搬運。

輸入格式

文件的第 11 行中有 11 個正整數 nn,表示有 nn 個倉庫。

第 22 行中有 nn 個正整數,表示 nn 個倉庫的庫存量。

輸出格式

輸出最少搬運量。

輸入輸出樣例

輸入 #1複製

5
17 9 14 16 4

輸出 #1複製

11

說明/提示

1≤n≤100

思路:(一些其他的解法

建了個如下的圖

 

ac代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#include<unordered_map>
#define mod (1000000007)
using namespace std;
typedef long long ll;
const int MAX = 2e5 + 5;
const int inf = 0x3f3f3f3f;
struct node {
    int v,f,w,nxt;
} e[50005<<2];
int n,m,N;
int head[MAX],d[MAX],vis[MAX],tot=1,p[MAX];
void add(int u,int v,int f,int cost=0) {
    e[++tot].v = v;e[tot].f = f;e[tot].w = cost;e[tot].nxt = head[u];head[u] = tot;
    e[++tot].v = u;e[tot].f = 0; e[tot].w = -cost;e[tot].nxt = head[v];head[v] = tot;
}
bool bfs(int s,int t) {
    for(int i = 0; i<=N; i++) 
	d[i]=inf,vis[i]=0;
    d[s]=0;
    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=e[i].nxt) {
            int j=e[i].v;
            if(e[i].f&&d[j]>d[u]+e[i].w) {
                d[j]=d[u]+e[i].w;
                p[j]=i;
                if(!vis[j])vis[j]=1,q.push(j);
            }
        }
    }
    return d[t]<inf;
}
int MCMF(int s,int t,int &flow) {
    int ans=0;
    while(bfs(s,t)) {
        int x=t,f=inf;
        while(x!=s) {
            f = min(f,e[p[x]].f),x=e[p[x]^1].v;
        }
        flow += f;
        ans+=1LL*d[t]*f;
        x=t;
        while(x!=s) {
            e[p[x]].f-=f,e[p[x]^1].f+=f;
            x=e[p[x]^1].v;
        }
    }
    return ans;
}

int main() {
    scanf("%d",&n);
    int st=n,ed=n+1,fl=0,x;N=ed;
    for(int i=0;i<=ed;i++) head[i]=-1;
    int sum=0;
	for(int i=0;i<n;i++){
    	scanf("%d",&x);
    	sum+=x;
		add(st,i,x,0);
	} 
	for(int i=0;i<n;i++){
		add(i,(i+1)%n,inf,1);
		add(i,(i-1+n)%n,inf,1);
	} 
	sum/=n;
    for(int i=0;i<n;i++){
		add(i,ed,sum,0);
	} 
	printf("%d\n",MCMF(st,ed,fl));
	
	return 0 ;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章