• 「网络流 24 题」负载平衡


    G 公司有 (n) 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 (n) 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。

    这道题我们建立一个超级源点和超级汇点,源点向每个仓库连边,容量为仓库库存,仓库向汇点连边,容量为库存平均值。每一个点向左右连边,边权为inf。

    对于这些边,我们都需要建一条与他们方向相反,容量为 (0) ,费用为原边的相反数。

    然后直接跑一下最小费用最大流,费用即为解。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    int read() {
        int a = 0, x = 1;
        char ch = getchar();
        while (ch > '9' || ch < '0') {
            if (ch == '-')
                x = -1;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9') {
            a = a * 10 + ch - '0';
            ch = getchar();
        }
        return a * x;
    }
    const int N = 807, inf = 1e9 + 7;
    ;
    int n, arr[N], sum = 0;
    
    int s, t, pre1[N], pre2[N];
    
    int head[N], go[N], nxt[N], val[N], lim[N], cnt = -1;
    void add(int u, int v, int r, int w) {
        go[++cnt] = v;
        nxt[cnt] = head[u];
        head[u] = cnt;
        val[cnt] = w, lim[cnt] = r;
    }
    int dis[N], ins[N];
    bool SPFA(int pos) {
        memset(ins, 0, sizeof(ins));
        queue<int> q;
        for (int i = 1; i <= n + 1; i++) dis[i] = inf;
        dis[pos] = 0, ins[pos] = 1;
        q.push(pos);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            ins[u] = 0;
            //	printf("%d 
    ",u);
            for (int e = head[u]; ~e; e = nxt[e]) {
                int v = go[e];
                if (!lim[e])
                    continue;
                if (dis[v] > dis[u] + val[e]) {
                    dis[v] = dis[u] + val[e];
                    pre1[v] = u, pre2[v] = e;
                    if (!ins[v]) {
                        q.push(v);
                        ins[v] = 1;
                    }
                }
            }
        }
        return dis[t] != inf;
    }
    
    void print(int i) {
        if (i == s)
            printf("%d ", s);
        else {
            print(pre1[i]);
            printf("%d ", i);
        }
    }
    
    int main() {
        n = read();
        s = 0, t = n + 1;
        memset(head, -1, sizeof(head));
        memset(nxt, -1, sizeof(nxt));
        for (int i = 1; i <= n; i++) {
            arr[i] = read();
            //  add(0, i, arr[i], 0);
            //  add(i, 0, 0, 0);
            sum += arr[i];
        }
        sum /= n;
        for (int i = 1; i <= n; i++) {
            if (arr[i] < sum) {
                add(i, n + 1, sum - arr[i], 0);
                add(n + 1, i, 0, 0);
            } else {
                add(0, i, arr[i] - sum, 0);
                add(i, 0, 0, 0);
            }
            add(i, i % n + 1, inf, 1);
            add(i % n + 1, i, 0, -1);
            add(i % n + 1, i, inf, 1);
            add(i, i % n + 1, 0, -1);
        }
        int ans = 0;
        // printf("%d
    ",sum);
        while (SPFA(s)) {
            ///	printf("!");
            int tmp = inf;
            for (int i = t; i != s; i = pre1[i]) tmp = min(tmp, lim[pre2[i]]);
            ans += dis[t] * tmp;
            //     print(t);
            //    putchar('
    ');
            for (int i = t; i != s; i = pre1[i]) lim[pre2[i]] -= tmp, lim[pre2[i] ^ 1] += tmp;
            // printf("%d %d
    ",tmp,ans);
        }
        printf("%d", ans);
        return 0;
    }
    
  • 相关阅读:
    Java的代理proxy机制
    Java 编译器 javac 笔记:javac API、注解处理 API 与 Lombok 原理
    Java 运行时获取方法参数名
    python 之 list 和 dict 置空
    Python 模块(Module)调用
    Python 模块(Module)及包
    Mybatis中进行批量更新(updateBatch)
    可持久化线段树+主席树+动态主席树
    无向图的割点与割边
    [NOIP2016] 愤怒的小鸟 题解
  • 原文地址:https://www.cnblogs.com/nao-nao/p/13695207.html
Copyright © 2020-2023  润新知