P4016 负载平衡问题 网络流重温

P4016 负载平衡问题

这个题目现在第二次做,感觉没有这么简单,可能是我太久没有写这种题目了,基本上都忘记了,所以我连这个是费用流都没有看出来。

有点小伤心,知道是费用流之后,我居然还拆点了。

这个写完之后确实感觉没有那么难,但是写的过程还是很艰辛的,这个为什么是一个费用流呢,

因为我们知道每移动一个单位的货物,就会产生一单位的费用,所以这个就是费用流。

再而为什么这个不要拆点呢,因为每一个点都是只有一种属性,要么就是多了要输出,要么就是少了要进入,这个其实我也有点不是很清楚。

还没有完全弄明白。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <string>
#include <iostream>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 3e5 + 10;
typedef long long ll;
struct edge
{
    int u, v, c, f, cost;
    edge(int u=0,int v=0,int c=0,int f=0,int cost=0):u(u),v(v),c(c),f(f),cost(cost){}
};
vector<edge>e;
vector<int>G[maxn];
int a[maxn], p[maxn], inq[maxn], d[maxn], n, m;
void init(int n)
{
    for (int i = 0; i <= n; i++) G[i].clear();
    e.clear();
}
void addedge(int u,int v,int c,int cost)
{
    e.push_back(edge(u, v, c, 0, cost));
    e.push_back(edge(v, u, 0, 0, -cost));
    int m = e.size();
    G[u].push_back(m - 2);
    G[v].push_back(m - 1);
}
bool spfa(int s,int t,int &flow,ll &cost)
{
    memset(d, inf, sizeof(d));
    memset(inq, 0, sizeof(inq));
    d[s] = 0, inq[s] = 1;
    p[s] = 0, a[s] = inf;
    queue<int>que;
    que.push(s);
    while(!que.empty())
    {
        int u = que.front(); que.pop();
        inq[u] = 0;
        for(int i=0;i<G[u].size();i++)
        {
            edge &now = e[G[u][i]];
            int v = now.v;
            if(now.c>now.f&&d[v]>d[u]+now.cost)
            {
                d[v] = d[u] + now.cost;
                p[v] = G[u][i];
                a[v] = min(a[u], now.c - now.f);
                if (!inq[v]) que.push(v), inq[v] = 1;
            }
        }
    }
    if (d[t] == inf) return false;
    flow += a[t];
    cost += d[t] * 1ll * a[t];
    for(int u=t;u!=s;u=e[p[u]].u)
    {
        e[p[u]].f += a[t];
        e[p[u] ^ 1].f -= a[t];
    }
    return true;
}

int MincostMaxflow(int s,int t,ll &cost)
{
    cost = 0;
    int flow = 0;
    while (spfa(s, t, flow, cost));
    return flow;
}

int main() {
    int n, sum = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sum += a[i];
    sum /= n;
    int s = 0, t = n + 1;
    for(int i=1;i<=n;i++)
    {
        if (a[i] > sum) addedge(s, i, a[i] - sum, 0);
        else addedge(i, t, sum - a[i], 0);
        if(i==1)
        {
            addedge(1, 2, inf, 1);
            addedge(1, n, inf, 1);
        }
        else if(i==n)
        {
            addedge(n, 1, inf, 1);
            addedge(n, n - 1, inf, 1);
        }
        else
        {
            addedge(i, i + 1, inf, 1);
            addedge(i, i - 1, inf, 1);
        }
    }
    ll ans = 0;
    MincostMaxflow(s, t, ans);
    printf("%lld
", ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/EchoZQN/p/11232013.html