LOJ6013 负载平衡 [最小费用最大流]

负载平衡

题目描述见链接 .


color{red}{正解部分}

将仓库分为两个类型, 第一个类型为稀缺货物的仓库 {ai}{a_i}, aia_i平均值xix_i,
第二个类型为富余货物的仓库 {bi}{b_i}, bib_i平均值yiy_i,

然后建立 超级源点 SS超级汇点 TT,

  • SSaia_i费用00, 容量xIx_I 的边 .
  • bib_iTT费用00, 容量yiy_i 的边 .
  • 相邻的仓库连 费用11, 容量infinf无向边 .

color{red}{实现部分}

#include<bits/stdc++.h>
#define reg register

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 505;
const int inf = 0x3f3f3f3f;
const int S = 101, T = 102;

int N;
int Ans;
int num0;
int Tmp_1;
int A[maxn];
int Dis[maxn];
int head[maxn];
int Pre[maxn][2];

bool vis[maxn];

struct Edge{ int nxt, to, w, c, f; } edge[maxn << 2];

void Add(int from, int to, int w, int cup, int flow){ 
        edge[++ num0] = (Edge){ head[from], to, w, cup, flow };
        head[from] = num0;
}

bool spfa(){
        memset(Dis, 0x3f, sizeof Dis);
        std::queue <int> Q; Q.push(S); Dis[S] = 0;
        while(!Q.empty()){
                int ft = Q.front(); Q.pop(); vis[ft] = 0;
                for(reg int i = head[ft]; i; i = edge[i].nxt){
                        int to = edge[i].to;
                        if(Dis[to] > Dis[ft] + edge[i].w && edge[i].c > edge[i].f){
                                Dis[to] = Dis[ft] + edge[i].w;
                                Pre[to][0] = ft, Pre[to][1] = i;
                                if(!vis[to]) vis[to] = 1, Q.push(to);
                        }
                }
        }
        return Dis[T] != inf;
}

void Mmflow(){
        while(spfa()){
                int t = T, mf = inf;
                while(t != S){
                        int id = Pre[t][1];
                        mf = std::min(mf, edge[id].c-edge[id].f);
                        t = Pre[t][0];
                }
                Ans += mf * Dis[T], t = T;
                while(t != S){
                        int id = Pre[t][1];
                        edge[id].f += mf, edge[id^1].f -= mf;
                        t = Pre[t][0];
                }
        }
}

int main(){
        N = read();
        for(reg int i = 1; i <= N; i ++) Tmp_1 += (A[i] = read());
        Tmp_1 /= N, num0 = 1;
        for(reg int i = 1; i <= N; i ++){
                if(A[i] > Tmp_1) Add(S, i, 0, A[i]-Tmp_1, 0), Add(i, S, 0, 0, 0);
                else if(A[i] < Tmp_1) Add(i, T, 0, Tmp_1-A[i], 0), Add(T, i, 0, 0, 0);
        }
        for(reg int i = 1; i <= N; i ++){
                if(i != 1) Add(i, i-1, 1, inf, 0), Add(i-1, i, -1, 0, 0);
                if(i != N) Add(i, i+1, 1, inf, 0), Add(i+1, i, -1, 0, 0);
        }
        Add(1, N, 1, inf, 0), Add(N, 1, -1, 0, 0);
        Add(N, 1, 1, inf, 0), Add(1, N, -1, 0, 0);
        Mmflow();
        printf("%d
", Ans);
        return 0;
}
原文地址:https://www.cnblogs.com/zbr162/p/11822445.html