[CODEVS1916] 负载平衡问题(最小费用最大流)

Posted 蒟蒻zht的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CODEVS1916] 负载平衡问题(最小费用最大流)相关的知识,希望对你有一定的参考价值。

传送门

 

输入所有 a[i],求出平均值 sum,每个 a[i] -= sum

那么如果 a[i] > 0,从 s 向 i 连一条容量为 a[i] 费用为 0 的有向边

  如果 a[i] < 0,从 i 向 t 连一条容量为 -a[i] 费用为 0 的有向边

每个点 i 和它相邻的两个点连一条容量为 INF 费用为 1 的有向边

 

求出最小费用最大流即为答案

 

——代码

技术分享
  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #define INF 1e9
  6 #define N 1000001
  7 #define min(x, y) ((x) < (y) ? (x) : (y))
  8 
  9 int n, cnt, s, t;
 10 int a[101], dis[N], pre[N];
 11 int head[N], to[N << 1], val[N << 1], cost[N << 1], next[N << 1];
 12 bool vis[N];
 13 
 14 inline int read()
 15 {
 16     int x = 0, f = 1;
 17     char ch = getchar();
 18     for(; !isdigit(ch); ch = getchar()) if(ch == -) f = -1;
 19     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - 0;
 20     return x * f;
 21 }
 22 
 23 inline void add(int x, int y, int z, int c)
 24 {
 25     to[cnt] = y;
 26     val[cnt] = z;
 27     cost[cnt] = c;
 28     next[cnt] = head[x];
 29     head[x] = cnt++;
 30 }
 31 
 32 inline bool spfa()
 33 {
 34     int i, u, v;
 35     std::queue <int> q;
 36     memset(vis, 0, sizeof(vis));
 37     memset(pre, -1, sizeof(pre));
 38     memset(dis, 127 / 3, sizeof(dis));
 39     q.push(s);
 40     dis[s] = 0;
 41     while(!q.empty())
 42     {
 43         u = q.front(), q.pop();
 44         vis[u] = 0;
 45         for(i = head[u]; i ^ -1; i = next[i])
 46         {
 47             v = to[i];
 48             if(val[i] && dis[v] > dis[u] + cost[i])
 49             {
 50                 dis[v] = dis[u] + cost[i];
 51                 pre[v] = i;
 52                 if(!vis[v])
 53                 {
 54                     q.push(v);
 55                     vis[v] = 1;
 56                 }
 57             }
 58         }
 59     }
 60     return pre[t] ^ -1;
 61 }
 62 
 63 inline int dinic()
 64 {
 65     int i, d, sum = 0;
 66     while(spfa())
 67     {
 68         d = INF;
 69         for(i = pre[t]; i ^ -1; i = pre[to[i ^ 1]]) d = min(d, val[i]);
 70         for(i = pre[t]; i ^ -1; i = pre[to[i ^ 1]])
 71         {
 72             val[i] -= d;
 73             val[i ^ 1] += d;
 74         }
 75         sum += dis[t] * d;
 76     }
 77     return sum;
 78 }
 79 
 80 int main()
 81 {
 82     int i, j, x, sum = 0;
 83     n = read();
 84     s = 0, t = n + 1;
 85     memset(head, -1, sizeof(head));
 86     for(i = 1; i <= n; i++)
 87     {
 88         a[i] = read();
 89         sum += a[i];
 90     }
 91     sum /= n;
 92     for(i = 1; i <= n; i++) a[i] -= sum;
 93     for(i = 1; i <= n; i++)
 94     {
 95         if(a[i] > 0) add(s, i, a[i], 0), add(i, s, 0, 0);
 96         if(a[i] < 0) add(i, t, -a[i], 0), add(t, i, 0, 0);
 97         if(i == 1)
 98         {
 99             add(i, 2, INF, 1), add(2, i, 0, -1);
100             add(i, n, INF, 1), add(n, i, 0, -1);
101         }
102         else if(i == n)
103         {
104             add(i, n - 1, INF, 1), add(n - 1, i, 0, -1);
105             add(i, 1, INF, 1), add(1, i, 0, -1);
106         }
107         else
108         {
109             add(i, i + 1, INF, 1), add(i + 1, i, 0, -1);
110             add(i, i - 1, INF, 1), add(i - 1, i, 0, -1);
111         }
112     }
113     printf("%d\n", dinic());
114     return 0;
115 }
View Code

 

以上是关于[CODEVS1916] 负载平衡问题(最小费用最大流)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P4016 负载平衡问题(最小费用最大流)

P4016 负载平衡问题(MCMF)

Codevs1033蚯蚓的游戏问题-费用流

[CODEVS1915] 分配问题(最小费用最大流)

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

CODEVS1078最小生成树