【2020HDU多校】第二场1005(HDU6767)New Equipments——费用流

题目链接

题目大意

给出 $n$ 个工人和 $m$ 件装备,装备的编号为 $1, 2, 3 … m$。
对于工人 $i$ ,他有三个参数 $a_i, b_i, c_i$,当为这个工人装备了第 $j$ 个装备时,需要花费 $a_i j ^ 2+ b_i j + c_i$ 的费用。
当为 $k$ 个工人装备上装备时,最小花费是多少。
对所有的 $k$ 的情况均需要输出

分析

费用流
将每个员工与源点链接,取每个员工的二次函数曲线的最小值附近的 $n$ 个点,与员工相连,所有的在二次函数曲线上的点与汇点相连,员工连接到二次函数的线需要设定费用,其他线费用均为 $0$,所有线的流量均为 $1$

输出每次 spfa 过程中得到的费用即可

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <bits/stdc++.h>

using namespace std;

#define ll long long

const ll maxn = 3000;
const ll INF = 0x3f3f3f3f3f3f3f3f;

bool flag;

struct Edge {
ll from, to, cap, flow, cost;

Edge(ll u, ll v, ll c, ll f, ll cc)
: from(u), to(v), cap(c), flow(f), cost(cc) {}
};

struct MCMF {
ll n, m;
vector<Edge> edges;
vector<ll> G[maxn];
ll inq[maxn]; //是否在队列中
ll d[maxn]; //bellmanford
ll p[maxn]; //上一条弧
ll a[maxn]; //可改进量
void init(ll nn) {
this->n = nn;
for (ll i = 0; i <= n; ++i) G[i].clear();
edges.clear();
}

void addEdge(ll from, ll to, ll cap, ll cost) {
edges.emplace_back(Edge(from, to, cap, 0, cost));
edges.emplace_back(Edge(to, from, 0, 0, -cost));
m = (ll) (edges.size());
G[from].emplace_back(m - 2);
G[to].emplace_back(m - 1);
}

bool spfa(ll s, ll t, ll &flow, ll &cost) {
for (ll i = 1; i <= n; ++i) d[i] = INF;
memset(inq, 0, sizeof(inq));
d[s] = 0;
inq[s] = 1;
p[s] = 0;
queue<ll> q;
a[s] = INF;
q.push(s);
while (!q.empty()) {
ll u = q.front();
q.pop();
inq[u] = 0;
for (ll i = 0; i < (ll) (G[u].size()); ++i) {
Edge &e = edges[G[u][i]];
if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if (!inq[e.to]) {
q.push(e.to);
inq[e.to] = 1;
}
}
}
}
if (d[t] == INF) return false;
flow += a[t];
cost += (ll) d[t] * (ll) a[t];
cout << (flag ? " " : "") << cost;
flag = true;
for (ll u = t; u != s; u = edges[p[u]].from) {
edges[p[u]].flow += a[t];
edges[p[u] ^ 1].flow -= a[t];
}
return true;
}

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

struct Node {
ll a, b, c;
ll l, r;

ll cal(ll x) {
return a * x * x + b * x + c;
}

void make(ll n, ll m) {
ll mid = -b / 2 / a;
l = mid - n / 2 - 1;
r = mid + n / 2 + 1;
l = max(1ll, l);
r = min(m, r);
if (r == m) {
l = r - n - 2;
} else if (l == 1) {
r = l + n + 2;
}
}
} node[60];

void solve() {
ll T;
cin >> T;
for (ll ts = 0; ts < T; ++ts) {
flag = false;
unordered_map<ll, ll> trans;
ll n, m;
cin >> n >> m;
ll ind = 51;
for (ll i = 1; i <= n; ++i) {
cin >> node[i].a >> node[i].b >> node[i].c;
node[i].make(n, m);
ll l = node[i].l;
ll r = node[i].r;
assert(r - l < 60);
for (ll j = l; j <= r; ++j) {
if (trans.count(j)) continue;
trans.insert({j, ind++});
}
}
ll source = ind + 10, target = ind + 11;
mcmf.init(target + 10);
#ifdef ACM_LOCAL
cerr << target + 10 << endl;
#endif
for (auto &item : trans)
mcmf.addEdge(item.second, target, 1, 0);
for (ll i = 1; i <= n; ++i) {
mcmf.addEdge(source, i, 1, 0);
for (ll j = node[i].l; j <= node[i].r; ++j) {
mcmf.addEdge(i, trans[j], 1, node[i].cal(j));
}
}
ll cost;
mcmf.MincostMaxflow(source, target, cost);
cout << endl;
}
}

signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug;
while (cin >> acm_local_for_debug) {
if (acm_local_for_debug == '$') exit(0);
cin.putback(acm_local_for_debug);
if (test_index_for_debug > 20) {
throw runtime_error("Check the stdin!!!");
}
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
}
#else
solve();
#endif
return 0;
}


【2020HDU多校】第二场1005(HDU6767)New Equipments——费用流
https://blog.mauve.icu/2020/07/24/acm/2020-multi-school/HDU6767-2-1005-New-Equipments/
作者
Shiroha
发布于
2020年7月24日
许可协议