[网络流24题] 负载平衡问题

怎么每天都要被sb错误坑半天..建图的时候竟然忘记了反向边

这道题我们可以考虑把一个地方拆成两个点 x 1 , y 1 , 从源点向 x 1 连流量为物品数, 费用0的边, y 1 向汇点连所有物品平均数的边, 然后每个 x 1 向对应 y 1 连流量 i n f , 费用 0 的边, 然后对于物品间的运转, 相邻的连流量 i n f , 费用为 0 的边 一定要建双向边!!!我就是因为这里wa了很多遍, 例如 1 号点能向 n 号点运输, 那 n 号点肯定也可以向 1 号点运输, 这样子跑最小费用最大流即可
题目链接

#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define rel(x) ((x - 1) % n + 1)
#define inf (0x3f3f3f3f)

using namespace std;

const int maxn = 200 + 10, maxm = 1e5 + 10;
int n, a[maxn], sum, s, t;

namespace Mincost_Maxflow {
    int to[maxm << 1], head[maxn], nxt[maxm << 1], w[maxm << 1], v[maxm << 1], e = 1;
    int dis[maxn], vis[maxn], cost;

    void add(int x, int y, int z, int val) {
        to[++ e] = y;
        nxt[e]= head[x];
        head[x] = e;
        w[e] = z;
        v[e] = val;
        if(z) add(y, x, 0, -val);
    }

    bool SPFA() {
        queue<int> q;
        memset(vis, 0, sizeof(vis));
        memset(dis, inf, sizeof(dis));
        vis[s] = true, dis[s] = 0, q.push(s);
        while(!q.empty()) {
            int k = q.front(); q.pop();
            go(k, i) 
                if(w[i] && dis[to[i]] > dis[k] + v[i]) {
                    dis[to[i]] = dis[k] + v[i];
                    if(!vis[to[i]]) {
                        vis[to[i]] = true;
                        q.push(to[i]);
                    }
                }
            vis[k] = false;
        }
        return dis[t] != inf;
    }

    int dfs(int x, int flow) {
        vis[x] = flow;
        if(x == t || !flow)
            return flow;
        int used = 0;
        go(x, i) 
            if(dis[to[i]] == dis[x] + v[i] && !vis[to[i]]) {
                int di = dfs(to[i], min(flow, w[i]));
                w[i] -= di, w[i ^ 1] += di;
                flow -= di, used += di, cost += di * v[i];
                if(!flow) break;
            }
        return used;
    }

    int dinic() {
        int res = 0;
        while(SPFA()) {
            vis[t] = true;
            while(vis[t]) {
                memset(vis, 0, sizeof(vis));
                res += dfs(s, inf);
            }
        }
        return res;
    }

}

int main() {
#ifndef ONLINE_JUDGE
    freopen("4016.in", "r", stdin);
    freopen("4016.out", "w", stdout);
#endif
    scanf("%d", &n); s = n << 1 | 1, t = s + 1;
    For(i, 1, n) scanf("%d", &a[i]), sum += a[i];
    sum /= n;
    For(i, 1, n) Mincost_Maxflow::add(s, i, a[i], 0), Mincost_Maxflow::add(i + n, t, sum, 0);
    For(i, 1, n) {
        Mincost_Maxflow::add(i, i + n, inf, 0);
        Mincost_Maxflow::add(rel(i), rel(i + 1), inf, 1);
        Mincost_Maxflow::add(rel(i + 1), rel(i), inf, 1);
    }
    Mincost_Maxflow::dinic(), printf("%d\n", Mincost_Maxflow::cost);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/81289966