|
| 1 | +// CF Submission: https://codeforces.com/contest/1430/submission/95221926 |
| 2 | +// #pragma GCC optimize("Ofast") |
| 3 | +// #pragma GCC target("avx2,bmi,bmi2,lzcnt") |
| 4 | +// #define NDEBUG |
| 5 | + |
| 6 | +#include <bits/extc++.h> |
| 7 | +#include <x86intrin.h> |
| 8 | + |
| 9 | +struct rep { |
| 10 | + struct iter { |
| 11 | + int i; |
| 12 | + constexpr void operator++() { ++i; } |
| 13 | + constexpr int operator*() const { return i; } |
| 14 | + friend constexpr bool operator!=(iter a, iter b) { return *a != *b; } |
| 15 | + }; |
| 16 | + const int l, r; |
| 17 | + constexpr rep(int _l, int _r) : l(std::min(_l, _r)), r(_r) {} |
| 18 | + constexpr rep(int n) : rep(0, n) {} |
| 19 | + constexpr iter begin() const { return {l}; } |
| 20 | + constexpr iter end() const { return {r}; } |
| 21 | +}; |
| 22 | +struct per { |
| 23 | + struct iter { |
| 24 | + int i; |
| 25 | + constexpr void operator++() { --i; } |
| 26 | + constexpr int operator*() const { return i; } |
| 27 | + friend constexpr bool operator!=(iter a, iter b) { return *a != *b; } |
| 28 | + }; |
| 29 | + const int l, r; |
| 30 | + constexpr per(int _l, int _r) : l(std::min(_l, _r)), r(_r) {} |
| 31 | + constexpr per(int n) : per(0, n) {} |
| 32 | + constexpr iter begin() const { return {r - 1}; } |
| 33 | + constexpr iter end() const { return {l - 1}; } |
| 34 | +}; |
| 35 | +template <class T, class U> |
| 36 | +constexpr bool chmin(T& a, U&& b) { |
| 37 | + return b < a ? a = std::forward<U>(b), true : false; |
| 38 | +} |
| 39 | +template <class T, class U> |
| 40 | +constexpr bool chmax(T& a, U&& b) { |
| 41 | + return a < b ? a = std::forward<U>(b), true : false; |
| 42 | +} |
| 43 | + |
| 44 | +namespace atcoder { |
| 45 | + |
| 46 | +template <class Cap, class Cost> |
| 47 | +struct mcf_graph { |
| 48 | + public: |
| 49 | + mcf_graph() {} |
| 50 | + mcf_graph(int n) : _n(n), g(n) {} |
| 51 | + |
| 52 | + int add_edge(int from, int to, Cap cap, Cost cost) { |
| 53 | + assert(0 <= from && from < _n); |
| 54 | + assert(0 <= to && to < _n); |
| 55 | + int m = int(pos.size()); |
| 56 | + pos.push_back({from, int(g[from].size())}); |
| 57 | + int from_id = int(g[from].size()); |
| 58 | + int to_id = int(g[to].size()); |
| 59 | + if (from == to) to_id++; |
| 60 | + g[from].push_back(_edge{to, to_id, cap, cost}); |
| 61 | + g[to].push_back(_edge{from, from_id, 0, -cost}); |
| 62 | + return m; |
| 63 | + } |
| 64 | + |
| 65 | + struct edge { |
| 66 | + int from, to; |
| 67 | + Cap cap, flow; |
| 68 | + Cost cost; |
| 69 | + }; |
| 70 | + |
| 71 | + edge get_edge(int i) { |
| 72 | + int m = int(pos.size()); |
| 73 | + assert(0 <= i && i < m); |
| 74 | + auto _e = g[pos[i].first][pos[i].second]; |
| 75 | + auto _re = g[_e.to][_e.rev]; |
| 76 | + return edge{ |
| 77 | + pos[i].first, _e.to, _e.cap + _re.cap, _re.cap, _e.cost, |
| 78 | + }; |
| 79 | + } |
| 80 | + std::vector<edge> edges() { |
| 81 | + int m = int(pos.size()); |
| 82 | + std::vector<edge> result(m); |
| 83 | + for (int i = 0; i < m; i++) { |
| 84 | + result[i] = get_edge(i); |
| 85 | + } |
| 86 | + return result; |
| 87 | + } |
| 88 | + |
| 89 | + std::pair<Cap, Cost> flow(int s, int t) { |
| 90 | + return flow(s, t, std::numeric_limits<Cap>::max()); |
| 91 | + } |
| 92 | + std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) { |
| 93 | + return slope(s, t, flow_limit).back(); |
| 94 | + } |
| 95 | + std::vector<std::pair<Cap, Cost>> slope(int s, int t) { |
| 96 | + return slope(s, t, std::numeric_limits<Cap>::max()); |
| 97 | + } |
| 98 | + std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) { |
| 99 | + assert(0 <= s && s < _n); |
| 100 | + assert(0 <= t && t < _n); |
| 101 | + assert(s != t); |
| 102 | + // variants (C = maxcost): |
| 103 | + // -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0 |
| 104 | + // reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge |
| 105 | + std::vector<Cost> dual(_n, 0), dist(_n); |
| 106 | + std::vector<int> pv(_n), pe(_n); |
| 107 | + std::vector<bool> vis(_n); |
| 108 | + auto dual_ref = [&]() { |
| 109 | + std::fill(dist.begin(), dist.end(), std::numeric_limits<Cost>::max()); |
| 110 | + std::fill(pv.begin(), pv.end(), -1); |
| 111 | + std::fill(pe.begin(), pe.end(), -1); |
| 112 | + std::fill(vis.begin(), vis.end(), false); |
| 113 | + struct Q { |
| 114 | + Cost key; |
| 115 | + int to; |
| 116 | + bool operator<(Q r) const { return key > r.key; } |
| 117 | + }; |
| 118 | + std::priority_queue<Q> que; |
| 119 | + dist[s] = 0; |
| 120 | + que.push(Q{0, s}); |
| 121 | + while (!que.empty()) { |
| 122 | + int v = que.top().to; |
| 123 | + que.pop(); |
| 124 | + if (vis[v]) continue; |
| 125 | + vis[v] = true; |
| 126 | + if (v == t) break; |
| 127 | + // dist[v] = shortest(s, v) + dual[s] - dual[v] |
| 128 | + // dist[v] >= 0 (all reduced cost are positive) |
| 129 | + // dist[v] <= (n-1)C |
| 130 | + for (int i = 0; i < int(g[v].size()); i++) { |
| 131 | + auto e = g[v][i]; |
| 132 | + if (vis[e.to] || !e.cap) continue; |
| 133 | + // |-dual[e.to] + dual[v]| <= (n-1)C |
| 134 | + // cost <= C - -(n-1)C + 0 = nC |
| 135 | + Cost cost = e.cost - dual[e.to] + dual[v]; |
| 136 | + if (dist[e.to] - dist[v] > cost) { |
| 137 | + dist[e.to] = dist[v] + cost; |
| 138 | + pv[e.to] = v; |
| 139 | + pe[e.to] = i; |
| 140 | + que.push(Q{dist[e.to], e.to}); |
| 141 | + } |
| 142 | + } |
| 143 | + } |
| 144 | + if (!vis[t]) { |
| 145 | + return false; |
| 146 | + } |
| 147 | + |
| 148 | + for (int v = 0; v < _n; v++) { |
| 149 | + if (!vis[v]) continue; |
| 150 | + // dual[v] = dual[v] - dist[t] + dist[v] |
| 151 | + // = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + |
| 152 | + // (shortest(s, v) + dual[s] - dual[v]) = - shortest(s, t) + |
| 153 | + // dual[t] + shortest(s, v) = shortest(s, v) - shortest(s, t) >= |
| 154 | + // 0 - (n-1)C |
| 155 | + dual[v] -= dist[t] - dist[v]; |
| 156 | + } |
| 157 | + return true; |
| 158 | + }; |
| 159 | + Cap flow = 0; |
| 160 | + Cost cost = 0, prev_cost_per_flow = -1; |
| 161 | + std::vector<std::pair<Cap, Cost>> result; |
| 162 | + result.push_back({flow, cost}); |
| 163 | + while (flow < flow_limit) { |
| 164 | + if (!dual_ref()) break; |
| 165 | + Cap c = flow_limit - flow; |
| 166 | + for (int v = t; v != s; v = pv[v]) { |
| 167 | + c = std::min(c, g[pv[v]][pe[v]].cap); |
| 168 | + } |
| 169 | + for (int v = t; v != s; v = pv[v]) { |
| 170 | + auto& e = g[pv[v]][pe[v]]; |
| 171 | + e.cap -= c; |
| 172 | + g[v][e.rev].cap += c; |
| 173 | + } |
| 174 | + Cost d = -dual[s]; |
| 175 | + flow += c; |
| 176 | + cost += c * d; |
| 177 | + if (prev_cost_per_flow == d) { |
| 178 | + result.pop_back(); |
| 179 | + } |
| 180 | + result.push_back({flow, cost}); |
| 181 | + prev_cost_per_flow = d; |
| 182 | + } |
| 183 | + return result; |
| 184 | + } |
| 185 | + |
| 186 | + private: |
| 187 | + int _n; |
| 188 | + |
| 189 | + struct _edge { |
| 190 | + int to, rev; |
| 191 | + Cap cap; |
| 192 | + Cost cost; |
| 193 | + }; |
| 194 | + |
| 195 | + std::vector<std::pair<int, int>> pos; |
| 196 | + std::vector<std::vector<_edge>> g; |
| 197 | +}; |
| 198 | + |
| 199 | +} // namespace atcoder |
| 200 | + |
| 201 | +template <class Cap, class Cost> |
| 202 | +struct min_cost_b_flow { |
| 203 | + struct result { |
| 204 | + bool feasible; |
| 205 | + Cost cost; |
| 206 | + std::vector<Cap> flow; |
| 207 | + std::vector<Cost> dual; |
| 208 | + }; |
| 209 | + |
| 210 | + min_cost_b_flow() {} |
| 211 | + explicit min_cost_b_flow(int n) : g(n + 2), b(n) {} |
| 212 | + |
| 213 | + int size() const { return std::size(b); } |
| 214 | + int add_edge(int src, int dst, Cap lower, Cap upper, Cost cost) { |
| 215 | + assert(0 <= src), assert(src < size()); |
| 216 | + assert(0 <= dst), assert(dst < size()); |
| 217 | + assert(lower <= upper); |
| 218 | + if (rev.push_back(cost < 0), rev.back()) { |
| 219 | + std::swap(src, dst); |
| 220 | + std::tie(lower, upper) = std::pair{-upper, -lower}; |
| 221 | + cost = -cost; |
| 222 | + } |
| 223 | + b[src] -= lower; |
| 224 | + b[dst] += lower; |
| 225 | + res.cost += lower * cost; |
| 226 | + res.flow.push_back(lower); |
| 227 | + return g.add_edge(src, dst, upper - lower, cost); |
| 228 | + } |
| 229 | + void add_supply(int v, Cap x) { |
| 230 | + assert(0 <= v), assert(v < size()); |
| 231 | + b[v] += x; |
| 232 | + } |
| 233 | + void add_demand(int v, Cap x) { |
| 234 | + assert(0 <= v), assert(v < size()); |
| 235 | + b[v] -= x; |
| 236 | + } |
| 237 | + |
| 238 | + result flow() { |
| 239 | + int source = size(), sink = source + 1; |
| 240 | + Cap positive{}, negative{}; |
| 241 | + for (int v = 0; v < size(); ++v) |
| 242 | + if (b[v] > 0) { |
| 243 | + g.add_edge(source, v, b[v], 0); |
| 244 | + positive += b[v]; |
| 245 | + } else if (b[v] < 0) { |
| 246 | + g.add_edge(v, sink, -b[v], 0); |
| 247 | + negative += -b[v]; |
| 248 | + } |
| 249 | + if (positive != negative) return {}; |
| 250 | + auto [flow, cost] = g.flow(source, sink); |
| 251 | + if (flow < positive) return {}; |
| 252 | + res.feasible = true; |
| 253 | + res.cost += cost; |
| 254 | + std::vector<std::vector<std::pair<int, Cost>>> h(size()); |
| 255 | + for (int i = 0; i < int(std::size(res.flow)); ++i) { |
| 256 | + auto e = g.get_edge(i); |
| 257 | + if (e.flow < e.cap) h[e.from].emplace_back(e.to, e.cost); |
| 258 | + if (e.flow > 0) h[e.to].emplace_back(e.from, -e.cost); |
| 259 | + res.flow[i] += e.flow; |
| 260 | + if (rev[i]) res.flow[i] = -res.flow[i]; |
| 261 | + } |
| 262 | + res.dual.resize(size()); |
| 263 | + std::vector<int> que(size()); |
| 264 | + std::iota(begin(que), end(que), 0); |
| 265 | + std::vector in_que(size(), true); |
| 266 | + for (int bg = 0; bg < int(std::size(que));) { |
| 267 | + int v = que[bg++]; |
| 268 | + in_que[v] = false; |
| 269 | + for (auto [u, c] : h[v]) { |
| 270 | + if (res.dual[v] + c < res.dual[u]) { |
| 271 | + res.dual[u] = res.dual[v] + c; |
| 272 | + if (not in_que[u]) in_que[u] = true, que.push_back(u); |
| 273 | + } |
| 274 | + } |
| 275 | + } |
| 276 | + return res; |
| 277 | + } |
| 278 | + |
| 279 | + private: |
| 280 | + atcoder::mcf_graph<Cap, Cost> g; |
| 281 | + std::vector<Cap> b; |
| 282 | + std::vector<bool> rev; |
| 283 | + result res{}; |
| 284 | +}; |
| 285 | + |
| 286 | +int main() { |
| 287 | + using namespace std; |
| 288 | + cin.tie(nullptr)->sync_with_stdio(false); |
| 289 | + int n, m; |
| 290 | + cin >> n >> m; |
| 291 | + min_cost_b_flow<int, int64_t> g(n); |
| 292 | + while (m--) { |
| 293 | + int x, y, w; |
| 294 | + cin >> x >> y >> w; |
| 295 | + --x, --y; |
| 296 | + g.add_edge(x, y, -1e7, w, 1); |
| 297 | + } |
| 298 | + auto ans = g.flow().dual; |
| 299 | + auto mx = *max_element(begin(ans), end(ans)); |
| 300 | + for (auto&& e : ans) e = mx - e; |
| 301 | + for (int i : rep(n)) cout << ans[i] << " \n"[i == n - 1]; |
| 302 | +} |
0 commit comments