标签:部分 sum stdout 需求 相同 color spfa 输入 upd
?问题描述:
G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最
少搬运量可以使n 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。
?编程任务:
对于给定的n 个环形排列的仓库的库存量,编程计算使n 个仓库的库存数量相同的最少
搬运量。
?数据输入:
由文件overload.in提供输入数据。文件的第1 行中有1 个正整数n(n<=100),表示有n
个仓库。第2 行中有n个正整数,表示n个仓库的库存量。
?结果输出:
程序运行结束时,将计算出的最少搬运量输出到文件overload.out中。
输入文件示例 输出文件示例
overload.in
5
17 9 14 16 4
overload.out
11
/* 设A[i]=库存-平均值 把点拆成两部分,一部分表示供应节点,一部分表示需求节点。 若A[i]>0,S向i连一条容量为A[i],费用为0的边。 若A[i]<0,i‘向T连一条容量为-A[i],费用为0的边。 对与相邻的i和j,i向j‘连一条容量为inf,费用为1的边,表示搬过去; 同时i向j连一条容量为inf,费用为1的边表示暂时搬过去但不满足需求。 (也可以先预处理出来最短路,然后直接做。) */ #include<iostream> #include<cstdio> #include<queue> #define N 210 #define inf 1000000000 using namespace std; int a[N],head[N],dis[N],inq[N],fa[N],n,S,T,cnt=1,ans; struct node{int v,f,w,pre;}e[N*10]; queue<int> q; void add(int u,int v,int f,int w){ e[++cnt].v=v;e[cnt].f=f;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt; e[++cnt].v=u;e[cnt].f=0;e[cnt].w=-w;e[cnt].pre=head[v];head[v]=cnt; } bool spfa(){ if(ans==13){ int aaa=1; } for(int i=0;i<=T;i++) dis[i]=inf; q.push(S);dis[S]=0; while(!q.empty()){ int u=q.front();q.pop();inq[u]=0; for(int i=head[u];i;i=e[i].pre) if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w){ dis[e[i].v]=dis[u]+e[i].w; fa[e[i].v]=i; if(!inq[e[i].v]){ q.push(e[i].v); inq[e[i].v]=1; } } } return dis[T]!=inf; } void updata(){ int i=fa[T],x=inf; while(i){ x=min(x,e[i].f); i=fa[e[i^1].v]; } i=fa[T]; while(i){ e[i].f-=x; e[i^1].f+=x; i=fa[e[i^1].v]; } ans+=x*dis[T]; } int main(){ freopen("overload.in","r",stdin); freopen("overload.out","w",stdout); scanf("%d",&n);int sum=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i]; S=0;T=n*2+1;sum/=n; for(int i=1;i<=n;i++) a[i]-=sum; for(int i=1;i<=n;i++){ if(a[i]>0) add(S,i,a[i],0); if(a[i]<0) add(i+n,T,-a[i],0); } for(int i=1;i<=n;i++){ int t1=i-1,t2=i%n+1; if(!t1) t1=n; add(i,t1,inf,1);add(i,t1+n,inf,1); add(i,t2,inf,1);add(i,t2+n,inf,1); } while(spfa()) updata(); printf("%d",ans); return 0; }
标签:部分 sum stdout 需求 相同 color spfa 输入 upd
原文地址:http://www.cnblogs.com/harden/p/6711188.html