結果
問題 | No.2642 Don't cut line! |
ユーザー | maeshun |
提出日時 | 2024-03-05 22:29:16 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 183 ms / 4,000 ms |
コード長 | 6,200 bytes |
コンパイル時間 | 4,368 ms |
コンパイル使用メモリ | 275,536 KB |
実行使用メモリ | 26,864 KB |
最終ジャッジ日時 | 2024-09-29 18:06:30 |
合計ジャッジ時間 | 10,213 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,820 KB |
testcase_01 | AC | 183 ms
26,220 KB |
testcase_02 | AC | 179 ms
26,864 KB |
testcase_03 | AC | 179 ms
22,896 KB |
testcase_04 | AC | 171 ms
22,644 KB |
testcase_05 | AC | 174 ms
24,176 KB |
testcase_06 | AC | 102 ms
6,816 KB |
testcase_07 | AC | 104 ms
6,816 KB |
testcase_08 | AC | 103 ms
6,816 KB |
testcase_09 | AC | 102 ms
6,820 KB |
testcase_10 | AC | 104 ms
6,816 KB |
testcase_11 | AC | 103 ms
6,816 KB |
testcase_12 | AC | 107 ms
6,816 KB |
testcase_13 | AC | 104 ms
6,820 KB |
testcase_14 | AC | 108 ms
6,816 KB |
testcase_15 | AC | 110 ms
6,816 KB |
testcase_16 | AC | 137 ms
11,136 KB |
testcase_17 | AC | 138 ms
21,656 KB |
testcase_18 | AC | 143 ms
20,596 KB |
testcase_19 | AC | 105 ms
17,692 KB |
testcase_20 | AC | 89 ms
9,216 KB |
testcase_21 | AC | 91 ms
6,816 KB |
testcase_22 | AC | 93 ms
9,216 KB |
testcase_23 | AC | 172 ms
23,692 KB |
testcase_24 | AC | 82 ms
9,456 KB |
testcase_25 | AC | 90 ms
9,088 KB |
testcase_26 | AC | 110 ms
6,816 KB |
testcase_27 | AC | 108 ms
17,144 KB |
testcase_28 | AC | 154 ms
22,032 KB |
testcase_29 | AC | 108 ms
7,296 KB |
testcase_30 | AC | 97 ms
8,576 KB |
testcase_31 | AC | 131 ms
18,856 KB |
testcase_32 | AC | 99 ms
7,808 KB |
testcase_33 | AC | 2 ms
6,816 KB |
testcase_34 | AC | 2 ms
6,820 KB |
testcase_35 | AC | 1 ms
6,820 KB |
ソースコード
#include <bits/stdc++.h> #include <atcoder/all> using namespace std; using namespace atcoder; #define rep(i, n) for(int i=0;i<(n);++i) #define rep1(i, n) for(int i=1;i<=(n);i++) #define ll long long using mint = modint998244353; using P = pair<ll,ll>; using lb = long double; using T = tuple<ll, ll, ll>; #ifdef LOCAL # include <debug_print.hpp> # define dbg(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__) #else # define dbg(...) (static_cast<void>(0)) #endif template<typename T> inline bool chmax(T &a, T b) { return ((a < b) ? (a = b, true) : (false)); } // 辺に情報があるときlcaをみて子に持たせる。 class Node { public: int depth, parent, top, idxf, idxb; Node() : parent(-1) {} }; template <class S, S (*op)(S, S), S (*e)()> class HLD { public: HLD() : HLD(vector<vector<int>>(0), -1) {} explicit HLD(vector<vector<int>> &tree, int root_) : HLD(tree, root_, vector<S>(int(tree.size()), e())) {} explicit HLD(vector<vector<int>> &tree, int root_, const vector<S> &v) : n(int(tree.size())), root(root_) { build_(tree, v); } void build(vector<vector<int>> &tree, int root_) { n = int(tree.size()); build(tree, root_, vector<S>(n, e())); } void build(vector<vector<int>> &tree, int root_, const vector<S> &v) { n = int(tree.size()); root = root_; build_(tree, v); } // set element to node void set(int node, S x) { stf.set(nodes[node].idxf, x); stb.set(nodes[node].idxb, x); } // lca int lca(int ln, int rn) { while (1) { int topl = nodes[ln].top, topr = nodes[rn].top; if (topl == topr) { if (nodes[ln].depth < nodes[rn].depth) return ln; else return rn; } if (nodes[topl].depth > nodes[topr].depth) ln = nodes[topl].parent; else rn = nodes[topr].parent; } } // path query S edge_query(int ln, int rn) { S prodl = e(), prodr = e(); while (1) { int topl = nodes[ln].top, topr = nodes[rn].top; if (topl == topr) { //子に情報があるから調整している if (nodes[ln].depth < nodes[rn].depth) { // rn is deeper than ln prodl = op(prodl, stf.prod(nodes[ln].idxf+1, nodes[rn].idxf+1)); } else { // ln is deeper than rn prodl = op(prodl, stb.prod(nodes[ln].idxb, nodes[rn].idxb)); } return op(prodl, prodr); } if (nodes[topl].depth > nodes[topr].depth) { prodl = op(prodl, stb.prod(nodes[ln].idxb, nodes[topl].idxb+1)); ln = nodes[topl].parent; } else { prodr = op(stf.prod(nodes[topr].idxf, nodes[rn].idxf+1), prodr); rn = nodes[topr].parent; } } } S vertex_query(int ln, int rn) { S prodl = e(), prodr = e(); while (1) { int topl = nodes[ln].top, topr = nodes[rn].top; if (topl == topr) { if (nodes[ln].depth < nodes[rn].depth) { // rn is deeper than ln prodl = op(prodl, stf.prod(nodes[ln].idxf, nodes[rn].idxf+1)); } else { // ln is deeper than rn prodl = op(prodl, stb.prod(nodes[ln].idxb, nodes[rn].idxb+1)); } return op(prodl, prodr); } if (nodes[topl].depth > nodes[topr].depth) { prodl = op(prodl, stb.prod(nodes[ln].idxb, nodes[topl].idxb+1)); ln = nodes[topl].parent; } else { prodr = op(stf.prod(nodes[topr].idxf, nodes[rn].idxf+1), prodr); rn = nodes[topr].parent; } } } private: int n, root; segtree<S, op, e> stf, stb; vector<Node> nodes; void build_(vector<vector<int>> &tree, const vector<S> &v) { assert(n == int(v.size())); assert(root < n); // create segtree stf = segtree<S, op, e>(n); stb = segtree<S, op, e>(n); nodes = vector<Node>(n); vector<int> heavy(n, -1); pp1(tree, heavy, root, root, 0); pp2(tree, v, heavy, 0, root, root, root); } // set heavy node, parent, depth int pp1(vector<vector<int>> &tree, vector<int> &heavy, int node, int p, int d) { nodes[node].parent = p; nodes[node].depth = d; int sz = 1, sz_max = 0, sz_c; for (int &c: tree[node]) { if (c == p) continue; sz_c = pp1(tree, heavy, c, node, d+1); // get child's size sz += sz_c; // update size if (chmax(sz_max, sz_c)) heavy[node] = c; // update heavy node } return sz; } // build segtree, set top int pp2(vector<vector<int>> &tree, const vector<S> &v, vector<int> &heavy, int tour_idx, int node, int p, int t) { nodes[node].idxf = tour_idx; stf.set(tour_idx++, v[node]); nodes[node].idxb = n - tour_idx; stb.set(n - tour_idx, v[node]); nodes[node].top = t; // set top if (heavy[node] >= 0) { // heavy node and depth first search tour_idx = pp2(tree, v, heavy, tour_idx, heavy[node], node, t); } for (int &c: tree[node]) { if (c == p || c == heavy[node]) continue; tour_idx = pp2(tree, v, heavy, tour_idx, c, node, c); // next node is top } return tour_idx; } }; int op(int a, int b) { return max(a,b); } int e(){ return 0; } int main() { int n, k; ll c; cin >> n >> k >> c; vector<vector<int>> g(n); vector<int> u(k), v(k), w(k), p(k); rep(i,k){ cin >> u[i] >> v[i] >> w[i] >> p[i]; --u[i];--v[i]; } vector<int> idx(k); rep(i,k) idx[i] = i; sort(idx.begin(),idx.end(),[&](int l, int r) { return w[l]<w[r]; }); dsu uf(n); ll cost = 0; int P = 0; vector<bool> used(k); rep(i,k) { int id = idx[i]; if(uf.same(u[id], v[id])) continue; else{ cost += w[id]; P = max(p[id],P); g[u[id]].push_back(v[id]); g[v[id]].push_back(u[id]); used[id] = true; uf.merge(u[id], v[id]); } } if(cost>c) { cout << -1 << endl; return 0; } int ans = P; HLD<int,op,e> hld(g,0); rep(i,k){ if(used[i]) { dbg(u[i], v[i], hld.lca(u[i],v[i])); hld.set(u[i]+v[i]-hld.lca(u[i], v[i]), w[i]); } } dbg(ans); rep(i,k) { if(used[i]) continue; int mx = hld.edge_query(u[i], v[i]); ll ncost = cost - mx + w[i]; dbg(u[i], v[i]); if(ncost<=c) { ans = max(ans, p[i]); } } cout << ans << endl; }