1. 程式人生 > >洛谷P4016 負載平衡問題(最小費用最大流)

洛谷P4016 負載平衡問題(最小費用最大流)

pre 昨天 base 最大流 cst freopen reg ret body

題目描述

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

輸入輸出格式

輸入格式:

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

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

輸出格式:

輸出最少搬運量。

輸入輸出樣例

輸入樣例#1: 復制
5
17 9 14 16 4
輸出樣例#1: 復制
11

說明

1 \leq n \leq 1001n100

昨天老師講課的時候總在冥冥之中感覺這題貌似做過,貌似可以用貪心水過去,看了題解發現的確可以用貪心水QWQ....

網絡流做法

其實很簡單,只是我太菜想的太復雜了QWQ...

從S向每個點連容量為庫存量,費用為0的邊

從每個點向T連容量為平均庫存量,費用為0的邊

在相鄰兩個點之間連容量為INF,費用為1的邊

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define AddEdge(x,y,z,f) add_edge(x,y,z,f),add_edge(y,x,-z,0)
using
namespace std; const int INF=1e8+10; const int MAXN=1e4+10; int N,M,S,T; int C[MAXN][MAXN]; struct node { int u,v,w,f,nxt; }edge[MAXN]; int head[MAXN],num=2; inline void add_edge(int x,int y,int z,int f) { edge[num].u=x; edge[num].v=y; edge[num].w=z; edge[num].f=f; edge[num].nxt
=head[x]; head[x]=num++; } int dis[MAXN],vis[MAXN],Pre[MAXN]; bool SPFA() { memset(dis,0xf,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int>q; q.push(S); dis[S]=0; while(q.size()!=0) { int p=q.front();q.pop(); vis[p]=0; for(int i=head[p];i!=-1;i=edge[i].nxt) { if(edge[i].f&&dis[edge[i].v]>dis[p]+edge[i].w) { dis[edge[i].v]=dis[p]+edge[i].w; Pre[edge[i].v]=i; if(!vis[edge[i].v]) vis[edge[i].v]=1,q.push(edge[i].v); } } } return dis[T]<INF; } int F() { int nowflow=INF; for(int now=T;now!=S;now=edge[Pre[now]].u) nowflow=min(nowflow,edge[Pre[now]].f); for(int now=T;now!=S;now=edge[Pre[now]].u) edge[Pre[now]].f-=nowflow, edge[Pre[now]^1].f+=nowflow; return nowflow*dis[T]; } void MCMF() { int ans=0; while(SPFA()) ans+=F(); printf("%d\n",abs(ans)); } int pre(int i) { if(i!=1) return i-1; else return N; } int nxt(int i) { if(i!=N) return i+1; else return 1; } int main() { #ifdef WIN32 freopen("a.in","r",stdin); #endif memset(head,-1,sizeof(head)); scanf("%d",&N); int tot=0; S=0,T=N+1; for(int i=1;i<=N;i++) { int x;scanf("%d",&x); AddEdge(S,i,0,x); tot+=x; } tot=tot/N; for(int i=1;i<=N;i++) AddEdge(i,T,0,tot); for(int i=1;i<=N;i++) { AddEdge(i,pre(i),1,INF); AddEdge(i,nxt(i),1,INF); } MCMF(); return 0; }

洛谷P4016 負載平衡問題(最小費用最大流)