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

    负载平衡问题

    题目链接

    (下文中(xxrightarrow{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. 向旁边的两个仓库连边:

    (ixrightarrow{+infty,1}i+1,ixrightarrow{+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__<<"
    "
    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<<"
    ";
    //	fclose(stdin);
    //	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    例20:希尔排序
    例19:直接插入排序
    例14:计算某日是该年的第几天
    为自己
    hdoj--1027--Ignatius and the Princess II(dfs)
    UESTC--758--P酱的冒险旅途(模拟)
    nyoj--990--蚂蚁感冒(模拟)(思维题)
    历届试题 邮局(dfs+剪枝)
    历届试题 数字游戏
    历届试题 回文数字
  • 原文地址:https://www.cnblogs.com/zh-dou/p/11535557.html
Copyright © 2011-2022 走看看