您的位置:首页 > 其它

[codeVS1916] 负载平衡问题(最小费用流,拆点)

2017-04-26 14:22 176 查看
题目链接:http://codevs.cn/problem/1916/

n个点之间可以相互传递值,每传递一次步骤+1。最终希望所有点的值相同,问最少步骤。

最终所有值应当是平均数avg,如何在两个相邻点之间传输值?可以先拆点,再建边:

将每一个点拆成两个点(两个点集分别记为①和②),同点②到①之间的容量为inf,费用为0。

拆完点后,按照要求每一个①点连向相邻两个点的②点,容量为inf,费用为1。

需要注意的是,保证移动完每一步可以判断是否能直接流向汇点,所以要在①点集合中向汇点建边,容量为avg,费用为0。

这里建图建挫了,大致是这样:



跑最小费用流就可以了。

PS:这么看来BNU校赛的A题也可以这么建模(虽然贪心过的)。

附链接,可以思考:https://www.bnuoj.com/v3/contest_show.php?cid=9056#problem/A

1 #include <bits/stdc++.h>
2 using namespace std;
3
4 typedef long long LL;
5 typedef struct Node {
6     int u, v, next;
7     LL c, w;
8 }Node;
9 const int maxn = 210;
10 const int maxm = 4010;
11 const LL mod = 0x3f3f3f3fLL;
12 const LL inf = (1LL<<55);
13 int tot, head[maxn];
14 LL dist[maxn];
15 LL cost, flow;
16 Node e[maxm];
17 int pre[maxn];
18 bool visit[maxn];
19 queue<int> Q;
20 int S, T, N;
21
22 void adde(int u, int v, LL c, LL w) {
23     e[tot].u = u; e[tot].v = v; e[tot].c = c; e[tot].w = w; e[tot].next = head[u]; head[u] = tot++;
24     e[tot].u = v; e[tot].v = u; e[tot].c = 0; e[tot].w = -w; e[tot].next = head[v]; head[v] = tot++;
25 }
26 bool spfa(int s, int t, int n) {
27     int i;
28     for(i = 0; i <= n; i++) {
29         dist[i] = inf;
30         visit[i] = 0;
31         pre[i] = -1;
32     }
33     while(!Q.empty()) Q.pop();
34     Q.push(s);
35     visit[s] = true;
36     dist[s] = 0;
37     pre[s] = -1;
38     while(!Q.empty()) {
39         int u = Q.front();
40         visit[u] = false;
41         Q.pop();
42         for(int j = head[u]; j != -1; j = e[j].next) {
43             if(e[j].c > 0 && dist[u] + e[j].w < dist[e[j].v]) {
44                 dist[e[j].v] = dist[u] + e[j].w;
45                 pre[e[j].v] = j;
46                 if(!visit[e[j].v]) {
47                     Q.push(e[j].v);
48                     visit[e[j].v] = true;
49                 }
50             }
51         }
52     }
53     if(dist[t] == inf) return false;
54     else return true;
55 }
56 LL ChangeFlow(int t) {
57     LL det = mod;
58     int u = t;
59     while(~pre[u]) {
60         u = pre[u];
61         det = min(det, e[u].c);
62         u = e[u].u;
63     }
64     u = t;
65     while(~pre[u]) {
66         u = pre[u];
67         e[u].c -= det;
68         e[u ^ 1].c += det;
69         u = e[u].u;
70     }
71     return det;
72 }
73 LL MinCostFlow(int s, int t, int n) {
74     LL mincost, maxflow;
75     mincost = maxflow = 0;
76     while(spfa(s, t, n)) {
77         LL det = ChangeFlow(t);
78         mincost += det * dist[t];
79         maxflow += det;
80     }
81     cost = mincost;
82     flow = maxflow;
83     return mincost;
84 }
85
86 int n;
87 int a[maxn];
88
89 int main() {
90     LL avg = 0;
91     scanf("%d", &n);
92     for(int i = 1; i <= n; i++) {
93         scanf("%d", &a[i]);
94         avg += a[i];
95     }
96     avg /= n;
97     tot = 0;
98     memset(head, -1, sizeof(head));
99     S = 0, T = 2 * n + 1; N = T + 1;
100     for(int i = 1; i <= n; i++) {
101         adde(0, i, a[i], 0);
102         adde(i+n, i, inf, 0);
103         adde(i, T, (LL)avg, 0);
104     }
105     for(int i = 1; i < n; i++) adde(i, i+n+1, inf, 1);
106     adde(n, n+1, inf, 1);
107     for(int i = 2; i <= n; i++) adde(i, i+n-1, inf, 1);
108     adde(1, 2*n, inf, 1);
109     cout << MinCostFlow(S, T, N) << endl;
110     return 0;
111 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: