zoukankan      html  css  js  c++  java
  • P4016 负载平衡问题 题解

    题目大意

    一个环上有(n)个仓库,每个仓库存储的货物数量不等,如何用最少搬运量可以使 (n) 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。

    P4016 负载平衡问题

    问题解决

    貌似这个就是一道奥数题,但是众所周知,(OI)不是(MO)我们考虑用(OI)的方法来解决

    每个点中的货物运输很难处理,但是总的数是不变的,而且(n)非常小,我们就可以考虑用费用流来解决这个问题

    我们先算出最终状态,也就是(avg= sum /n)

    • 建立一个超级原点,和超级汇点

    • 对于一个(a[i]-avg>0)的仓库,也就是说需要将货物从这里运走,所以从超级原点建一条到(a[i])的边,流量为(a[i]-avg),费用为(0)

    • 对于一个(a[i]-avg<0)的仓库,也就是说需要货物运进来,所以建一条从(a[i])到超级汇点的边,流量为(a[i]-avg),费用为(0)

    • (a[i])之间可以相互运,所以之间建一条边,流量为(INF),费用为(1),注意是环

    代码实现

    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int maxn=105,maxe=605,INF=0x3f3f3f3f;
    int N,avg,a[maxn],Ans;
    int lnk[maxn],nxt[maxe],son[maxe],w[maxe],c[maxe],cnt=1,st,ed,x[maxn];
    int dis[maxn],vis[maxn];
    int mincost;
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    void add_e(int x,int y,int z,int cost){son[++cnt]=y;w[cnt]=z;c[cnt]=cost;nxt[cnt]=lnk[x];lnk[x]=cnt;}
    void add_edge(int x,int y,int z,int cost){add_e(x,y,z,cost);add_e(y,x,0,-cost);}
    int spfa(){
    	queue<int> q;
    	memset(dis,INF,sizeof dis);
    	memset(vis,0,sizeof vis);
    	dis[st]=0;q.push(st);
    	while(!q.empty()){
    		int cur=q.front();q.pop();vis[cur]=0;
    		for(int j=lnk[cur];j;j=nxt[j]){
    			if(w[j]>0&&dis[son[j]]>dis[cur]+c[j]){
    				dis[son[j]]=dis[cur]+c[j];
    				if(!vis[son[j]]){vis[son[j]]=1;q.push(son[j]);}
    			}
    		}
    	}
    	return dis[ed]!=INF;
    }
    int DFS(int x,int delta){
    	if(x==ed)return delta;
    	vis[x]=1;int flow=0;
    	for(int j=lnk[x];j;j=nxt[j]){
    		if(!vis[son[j]]&&w[j]>0&&dis[son[j]]==dis[x]+c[j]){
    			int tmp=DFS(son[j],min(delta-flow,w[j]));
    			if(tmp){
    				mincost+=(c[j]*tmp);
    				w[j]-=tmp;w[j^1]+=tmp;flow+=tmp;
    			}
    		}
    	}
    	vis[x]=0;
    	return flow;
    }
    int Dinic(){
    	int maxflow=0;
    	while(spfa()){
    		while(1){
    			int temp=DFS(st,INF);
    			if(!temp)break;
    			maxflow+=temp;
    		}
    	}
    	return maxflow;
    }
    int main(){
    	N=read();for(int i=1;i<=N;i++) a[i]=read(),avg+=a[i];avg/=N;
    	st=0;ed=N+1;
    	for(int i=1;i<=N;i++){x[i]=a[i]-avg;if(x[i]>0)add_edge(st,i,x[i],0);if(x[i]<0)add_edge(i,ed,-x[i],0);}
    	for(int i=1;i<=N;i++){if(i!=1)add_edge(i,i-1,INF,1);if(i!=N)add_edge(i,i+1,INF,1);}
    	add_edge(1,N,INF,1);add_edge(N,1,INF,1);
    	Ans=Dinic();
    	printf("%d
    ",mincost);
    	return 0;
    }
    
  • 相关阅读:
    PAT Advanced 1067 Sort with Swap(0, i) (25分)
    PAT Advanced 1048 Find Coins (25分)
    PAT Advanced 1060 Are They Equal (25分)
    PAT Advanced 1088 Rational Arithmetic (20分)
    PAT Advanced 1032 Sharing (25分)
    Linux的at命令
    Sublime Text3使用指南
    IntelliJ IDEA创建第一个Groovy工程
    Sublime Text3 安装ftp插件
    Sublime Text3配置Groovy运行环境
  • 原文地址:https://www.cnblogs.com/martian148/p/15180117.html
Copyright © 2011-2022 走看看