結果
問題 | No.1288 yuki collection |
ユーザー | ei1333333 |
提出日時 | 2020-09-25 02:00:38 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 2,412 ms / 5,000 ms |
コード長 | 6,017 bytes |
コンパイル時間 | 2,672 ms |
コンパイル使用メモリ | 224,804 KB |
実行使用メモリ | 64,256 KB |
最終ジャッジ日時 | 2024-06-28 05:53:24 |
合計ジャッジ時間 | 40,630 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 3 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 3 ms
5,376 KB |
testcase_13 | AC | 1,311 ms
41,216 KB |
testcase_14 | AC | 1,257 ms
41,088 KB |
testcase_15 | AC | 810 ms
34,432 KB |
testcase_16 | AC | 1,012 ms
35,200 KB |
testcase_17 | AC | 1,405 ms
41,088 KB |
testcase_18 | AC | 1,153 ms
40,448 KB |
testcase_19 | AC | 1,180 ms
40,320 KB |
testcase_20 | AC | 1,523 ms
41,856 KB |
testcase_21 | AC | 1,810 ms
56,960 KB |
testcase_22 | AC | 2,017 ms
57,088 KB |
testcase_23 | AC | 2,038 ms
56,832 KB |
testcase_24 | AC | 1,539 ms
41,856 KB |
testcase_25 | AC | 1,208 ms
42,112 KB |
testcase_26 | AC | 1,186 ms
42,240 KB |
testcase_27 | AC | 1,148 ms
24,320 KB |
testcase_28 | AC | 1,323 ms
34,304 KB |
testcase_29 | AC | 799 ms
37,632 KB |
testcase_30 | AC | 536 ms
39,168 KB |
testcase_31 | AC | 691 ms
40,192 KB |
testcase_32 | AC | 619 ms
39,168 KB |
testcase_33 | AC | 2,363 ms
64,256 KB |
testcase_34 | AC | 1,503 ms
43,008 KB |
testcase_35 | AC | 1,662 ms
41,472 KB |
testcase_36 | AC | 298 ms
41,984 KB |
testcase_37 | AC | 1,363 ms
41,856 KB |
testcase_38 | AC | 2,412 ms
64,128 KB |
testcase_39 | AC | 2,383 ms
64,128 KB |
testcase_40 | AC | 148 ms
38,656 KB |
testcase_41 | AC | 2 ms
5,376 KB |
testcase_42 | AC | 2 ms
5,376 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; //BEGIN CUT HERE // O(m^2 \log m \log U) // U: maximum capacity enum Objective { MINIMIZE = +1, MAXIMIZE = -1, }; template< typename Flow, typename Cost, Objective objective = Objective::MINIMIZE > struct MinCostFlow { template< typename T > inline void chmin(T &x, T y) { x = min(x, y); } struct Edge { int src, dst; Flow flow, cap; Cost cost; int rev; Edge(int src, int dst, Flow cap, Cost cost, int rev) : src(src), dst(dst), flow(0), cap(cap), cost(cost), rev(rev) {} Flow residual_cap() const { return cap - flow; } }; struct EdgePtr { int v, e; EdgePtr(int v, int e) : v(v), e(e) {} }; int n; vector< vector< Edge>> G; vector< Flow > b; vector< Cost > p; MinCostFlow(int n) : n(n), G(n), b(n, 0) {} EdgePtr add_edge(int src, int dst, Flow lower, Flow upper, Cost cost) { int e = G[src].size(); int r = (src == dst ? e + 1 : G[dst].size()); assert(lower <= upper); G[src].emplace_back(src, dst, +upper, +cost * objective, r); G[dst].emplace_back(dst, src, -lower, -cost * objective, e); return EdgePtr(src, e); } const Edge &get_edge(EdgePtr ep) const { return G[ep.v][ep.e]; } void push(Edge &e, Flow amount) { e.flow += amount; G[e.dst][e.rev].flow -= amount; } void add_supply(int v, Flow amount) { b[v] += amount; } void add_demand(int v, Flow amount) { b[v] -= amount; } Cost residual_cost(const Edge &e) { return e.cost + p[e.src] - p[e.dst]; } vector< int > excess_vs, deficit_vs; void saturate_negative(const Flow delta) { for(auto &es:G) { for(auto &e:es) { Flow cap = e.residual_cap(); cap -= cap % delta; if(cap < 0 or residual_cost(e) < 0) { push(e, cap); b[e.src] -= cap; b[e.dst] += cap; } } } excess_vs.clear(); deficit_vs.clear(); for(int v = 0; v < n; v++) { if(b[v] > 0) excess_vs.emplace_back(v); if(b[v] < 0) deficit_vs.emplace_back(v); } } const Cost unreachable = std::numeric_limits< Cost >::max(); Cost farthest; vector< Cost > dist; vector< Edge * > parent; struct P { Cost first; int second; P(Cost first, int second) : first(first), second(second) {} bool operator<(const P o) const { return first > o.first; } }; priority_queue< P > pq; template< typename Predicate > void eliminate(vector< int > &vs, Predicate predicate) { vs.erase(remove_if(begin(vs), end(vs), predicate), end(vs)); } bool dual(const Flow delta) { eliminate(excess_vs, [&](int v) { return b[v] < +delta; }); eliminate(deficit_vs, [&](int v) { return b[v] > -delta; }); dist.assign(n, unreachable); for(int v:excess_vs) pq.emplace(dist[v] = 0, v); parent.assign(n, nullptr); auto emplace = [&](Edge &e) { if(e.residual_cap() < delta) return; Cost nxt = dist[e.src] + residual_cost(e); if(nxt >= dist[e.dst]) return; pq.emplace(dist[e.dst] = nxt, e.dst); parent[e.dst] = &e; }; farthest = 0; int deficit_count = 0; while(!pq.empty()) { Cost d = pq.top().first; int v = pq.top().second; pq.pop(); if(dist[v] < d) continue; farthest = d; if(b[v] <= -delta) deficit_count++; if(deficit_count >= (int) deficit_vs.size()) break; for(auto &e:G[v]) emplace(e); } pq = decltype(pq)(); for(int v = 0; v < n; v++) p[v] += min(dist[v], farthest); return deficit_count > 0; } void primal(const Flow delta) { for(int t:deficit_vs) { if(dist[t] > farthest) continue; Flow f = -b[t]; int v; for(v = t; parent[v]; v = parent[v]->src) chmin(f, parent[v]->residual_cap()); chmin(f, b[v]); f -= f % delta; if(f <= 0) continue; for(v = t; parent[v];) { auto &e = *parent[v]; push(e, f); int u = parent[v]->src; if(e.residual_cap() <= 0) parent[v] = nullptr; v = u; } b[t] += f; b[v] -= f; } } template< Flow SCALING_FACTOR = 2 > bool build() { p.resize(n); Flow max_flow = 1; for(auto t:b) max_flow = max({max_flow, t, -t}); for(auto &es:G) for(auto &e:es) max_flow = max({max_flow, e.residual_cap(), -e.residual_cap()}); Flow delta = 1; while(delta < max_flow) delta *= SCALING_FACTOR; for(; delta; delta /= SCALING_FACTOR) { saturate_negative(delta); while(dual(delta)) primal(delta); } return excess_vs.empty() and deficit_vs.empty(); } template< typename T=Cost > T get_cost() { T res = 0; for(auto &es:G) for(auto &e:es) res += T(e.flow) * T(e.cost) / T(objective); return res / T(2); } template< typename T=Cost > T get_gain() { return get_cost(); } vector< Cost > get_potential() { fill(p.begin(), p.end(), 0); for(int i = 0; i < n; i++) for(auto &es:G) for(auto &e:es) if(e.residual_cap() > 0) chmin(p[e.dst], p[e.src] + e.cost); return p; } }; template< typename Flow, typename Cost > using MaxGainFlow = MinCostFlow< Flow, Cost, Objective::MAXIMIZE >; int main() { int N; cin >> N; string S; cin >> S; vector< int > V(N); for(auto &v : V) cin >> v; MaxGainFlow< int64_t, int64_t > flow(N + N + 2); int X = N + N; int Y = X + 1; string tmp = "yuki"; for(int i = 0; i < N; i++) { flow.add_edge(2 * i, 2 * i + 1, 0, 1, V[i]); if(S[i] == 'i') { flow.add_edge(2 * i + 1, Y, 0, 1, 0); } else { if(S[i] == 'y') { flow.add_edge(X, 2 * i, 0, 1, 0); } int p = tmp.find(S[i]); for(int j = i + 1; j < N; j++) { if(tmp[p + 1] == S[j]) { flow.add_edge(2 * i + 1, 2 * j, 0, 1, 0); } } } } flow.add_edge(X, Y, 0, N / 4, 0); flow.add_supply(X, N / 4); flow.add_demand(Y, N / 4); flow.build(); cout << flow.get_cost() << "\n"; }