首页 > 代码库 > [CODEVS1916] 负载平衡问题(最小费用最大流)

[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         else108         {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] 负载平衡问题(最小费用最大流)