• 网络流24题之负载平衡问题


    题目链接:传送门

    初次看这道题是不是发现这道题和均分纸牌很像,只是一个是环一个是链而已,所以这道题明显可以贪心啊,但是因为这是网络流24题,所以还是把它当做网络流的题目来做吧

    这是一道费用流的题目,首先老规矩建立一个源点,汇点
    为什么要建啊?,问这个问题有两种可能性
    1.太强,请移步至传送门
    2.太弱,请移步至传送门

    怎么连接汇点和源点呢?贪心的想一下,要使所有仓库数量相等,所以应将多的仓库运往少的仓库,所以多的仓库应该贡献,连向源点。少的仓库应该得到,连向汇点,且费用为0。然后相邻节点有一条流量为inf,费用为1的边(注意这里为无向边)

    再来回到开始说所得这是一个环不是一个链,所以要特殊处理一下1和n节点

    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=10001;
    queue<int> q;
    int dis[N],f[N],pre[N],fa[N],head[N],cnt,n,m,s,t,x,y,z,w,ans,ans1,b[N];
    struct node {
        int to,next,v,w;
    } a[100001];
    void add(int x,int y,int c,int v) {
        a[++cnt].to=y;
        a[cnt].next=head[x];
        a[cnt].v=c;
        a[cnt].w=v;
        head[x]=cnt;
    }
    int spfa() {
        memset(dis,127,sizeof(dis));
        memset(f,0,sizeof(f));
        q.push(s);
        f[s]=1;
        int inf=dis[1];
        dis[s]=0;
        while(!q.empty()) {
            int now=q.front();
            q.pop();
            f[now]=0;
            for(int i=head[now]; i; i=a[i].next) {
                int v=a[i].to;
                if(dis[v]>dis[now]+a[i].w&&a[i].v) {
                    dis[v]=dis[now]+a[i].w;
                    fa[v]=now;
                    pre[v]=i;
                    if(!f[v])
                        q.push(v),f[v]=1;
                }
            }
        }
        if(dis[t]!=inf)
            return 1;
        return 0;
    }
    void answer() {
        while(spfa()) {
            int minx=2147483647;
            for(int i=t; i!=s; i=fa[i])
                minx=min(minx,a[pre[i]].v);
            ans1+=dis[t]*minx;
            for(int i=t; i!=s; i=fa[i]) {
                a[pre[i]].v-=minx;
                if(pre[i]%2)
                    a[pre[i]+1].v+=minx;
                else
                    a[pre[i]-1].v+=minx;
            }
        }
    }
    int main() {
        scanf("%d",&n),ans=0,t=n+1;
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]),ans+=b[i];
        for(int i=1;i<=n;++i)
            b[i]-=ans/n;
        for(int i=1;i<=n;++i){
            if(b[i]>0)
                add(s,i,b[i],0),add(i,s,0,0);
            else if(b[i]<0)
                add(i,t,-b[i],0),add(t,i,0,0);
        }
        for(int i=1;i<n;i++)
            add(i,i+1,100000000,1),add(i+1,i,0,-1),add(i+1,i,10000000,1),add(i,i+1,0,-1);
        add(n,1,ans,1),add(1,n,0,-1);
        add(1,n,ans,1),add(n,1,0,-1);
        answer();
        printf("%d",ans1);
        return 0;
    }
    
    
  • 相关阅读:
    PAT (Advanced Level) Practice 1071 Speech Patterns (25分)
    PAT (Advanced Level) Practice 1070 Mooncake (25分)
    PAT (Advanced Level) Practice 1069 The Black Hole of Numbers (20分)
    PAT (Advanced Level) Practice 1074 Reversing Linked List (25分)
    PAT (Advanced Level) Practice 1073 Scientific Notation (20分)
    第一次冲刺个人总结01
    构建之法阅读笔记01
    人月神话阅读笔记01
    四则运算2
    学习进度条(软件工程概论1-8周)
  • 原文地址:https://www.cnblogs.com/hbxblog/p/9724267.html
Copyright © 2020-2023  润新知