結果

問題 No.901 K-ary εxtrεεmε
ユーザー kcvlexkcvlex
提出日時 2019-10-09 21:09:41
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 321 ms / 3,000 ms
コード長 6,889 bytes
コンパイル時間 3,066 ms
コンパイル使用メモリ 191,500 KB
実行使用メモリ 34,212 KB
最終ジャッジ日時 2023-08-11 03:58:29
合計ジャッジ時間 11,893 ms
ジャッジサーバーID
(参考情報)
judge13 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 127 ms
34,212 KB
testcase_01 AC 1 ms
4,380 KB
testcase_02 AC 3 ms
4,376 KB
testcase_03 AC 2 ms
4,376 KB
testcase_04 AC 3 ms
4,376 KB
testcase_05 AC 3 ms
4,376 KB
testcase_06 AC 2 ms
4,376 KB
testcase_07 AC 236 ms
22,576 KB
testcase_08 AC 229 ms
22,572 KB
testcase_09 AC 250 ms
22,492 KB
testcase_10 AC 237 ms
22,560 KB
testcase_11 AC 245 ms
22,588 KB
testcase_12 AC 260 ms
22,584 KB
testcase_13 AC 232 ms
22,584 KB
testcase_14 AC 229 ms
22,544 KB
testcase_15 AC 220 ms
22,580 KB
testcase_16 AC 234 ms
22,588 KB
testcase_17 AC 304 ms
22,520 KB
testcase_18 AC 291 ms
22,580 KB
testcase_19 AC 321 ms
22,496 KB
testcase_20 AC 318 ms
22,528 KB
testcase_21 AC 293 ms
22,532 KB
testcase_22 AC 234 ms
22,856 KB
testcase_23 AC 226 ms
22,768 KB
testcase_24 AC 221 ms
22,972 KB
testcase_25 AC 221 ms
22,868 KB
testcase_26 AC 226 ms
22,880 KB
testcase_27 AC 313 ms
22,776 KB
testcase_28 AC 305 ms
22,588 KB
testcase_29 AC 308 ms
22,532 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// #define DEBUGGING
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ALL(V) (V).begin(), (V).end()
#define ALLR(V) (V).rbegin(), (V).rend()

template <typename T> using V = vector<T>;
template <typename T> using VV = V<V<T>>;
using ll = int64_t;
using ull = uint64_t;
using PLL = pair<ll, ll>;

template <typename T> const T& var_min(const T &t) { return t; }
template <typename T> const T& var_max(const T &t) { return t; }
template <typename T, typename... Tail> const T& var_min(const T &t, const Tail&... tail) { return min(t, var_min(tail...)); }
template <typename T, typename... Tail> const T& var_max(const T &t, const Tail&... tail) { return max(t, var_max(tail...)); }
template <typename T, typename... Tail> void chmin(T &t, const Tail&... tail) { t = var_min(t, tail...); }
template <typename T, typename... Tail> void chmax(T &t, const Tail&... tail) { t = var_max(t, tail...); }
template <typename T> const T& clamp(const T &t, const T &low, const T &high) { return max(low, min(high, t)); }
template <typename T> void chclamp(T &t, const T &low, const T &high) { t = clamp(t, low, high); }

namespace init__ {

struct InitIO {
    InitIO() {
        cin.tie(nullptr);
        ios_base::sync_with_stdio(false);
        cout << fixed << setprecision(30);
    }
} init_io;

}

#ifdef DEBUGGING
// #include "../debug/debug.cpp"
#include "../../debug/debug.cpp"
#else
#define DEBUG(...) 0
#define DEBUG_SEPARATOR_LINE 0
#endif

template <typename T>
T make_v(T init) { return init; }

template <typename T, typename... Tail>
auto make_v(T init, size_t s, Tail... tail) {
#define rec make_v(init, tail...)
    return V<decltype(rec)>(s, rec);
#undef rec
}

template <typename Graph>
struct HeavyLightDecomposition {
    ll root;
    const Graph &graph;
    V<ll> subtree_size, head, parent_node_idx, decomposed_id, component_id, heavy_edge_to;

    HeavyLightDecomposition(const Graph &graph)
        : root(0),
          graph(graph),
          subtree_size(graph.size()),
          head(graph.size()),
          parent_node_idx(graph.size()),
          decomposed_id(graph.size()),
          component_id(graph.size()),
          heavy_edge_to(graph.size())
    {
    }

    ll count_size(ll cur, ll pre) {
        ll ret = 1;
        parent_node_idx[cur] = pre;
        ll max_size = 0, max_size_to = -1;
        for(ll nxt : graph[cur]) {
            if(nxt == pre) continue;
            ll res = count_size(nxt, cur);
            if(max_size < res) {
                max_size = res;
                max_size_to = nxt;
            }
            ret += res;
        }
        heavy_edge_to[cur] = max_size_to;
        return subtree_size[cur] = ret;
    }

    ll get_decomposed_id(ll node) { return node == -1 ? -1 : decomposed_id[node]; }

    void build_component(ll cur, ll pre, ll &decomposed_id_counter, ll &total_hl) {
        decomposed_id[cur] = decomposed_id_counter++;
        component_id[cur] = total_hl;
        head[cur] = (get_decomposed_id(pre) == -1 ? cur :
                     component_id[cur] == component_id[pre] ? head[pre] : cur);

        if(heavy_edge_to[cur] != -1) build_component(heavy_edge_to[cur], cur, decomposed_id_counter, total_hl);

        for(ll nxt : graph[cur]) {
            if(nxt == pre || nxt == heavy_edge_to[cur]) continue;
            build_component(nxt, cur, decomposed_id_counter, ++total_hl);
        }
    }

    void decompose() {
        count_size(root, -1);
        ll decomposed_id_counter = 0;
        ll total_hl = 0;
        build_component(root, -1, decomposed_id_counter, total_hl);
    }

    // careful : when query handle edges
    template <typename T>
    T query(ll n1, ll n2, const function<T(ll, ll)> &calc_component, T identity, const function<T(T, T)> &merge) {
        T lval = identity, rval = identity;
        T result = identity;
        while(true) {
        }
        return result;
    }

    void query(ll n1, ll n2, const function<void(ll, ll)> &calc_component) {
        ll identity = 0;
        auto merge = [&](ll a, ll b) { return 0; };
        auto wrapper_calc = [&](ll a, ll b) { calc_component(a, b); return 0; };
        query<ll>(n1, n2, wrapper_calc, identity, merge);
    }
};

int main() {
    ll N;
    cin >> N;
    VV<ll> edges(N);
    map<PLL, ll> costs;
    for(ll i = 1; i < N; i++) {
        ll a, b, c;
        cin >> a >> b >> c;
        if(b < a) swap(a, b);
        edges[a].push_back(b);
        edges[b].push_back(a);
        costs[PLL(a, b)] = c;
    }
    
    HeavyLightDecomposition<VV<ll>> hld(edges);
    hld.decompose();
    V<ll> sum(N + 1);
    V<ll> nodes(N);
    V<ll> cost_to_parent(N);
    iota(ALL(nodes), 0ll);
    sort(ALL(nodes), [&](ll a, ll b) { return hld.decomposed_id[a] < hld.decomposed_id[b]; });
    for(ll i = 0; i < N; i++) {
        sum[i + 1] = sum[i];
        ll a = nodes[i], b = nodes[i + 1];
        PLL key(min(a, b), max(a, b));
        if(hld.component_id[a] == hld.component_id[b]) sum[i + 1] += costs[key];
        if(a == hld.head[a]) {
            ll p = hld.parent_node_idx[a];
            cost_to_parent[a] = costs[PLL(min(a, p), max(a, p))];
        }
    }

    DEBUG(cost_to_parent);

    ll Q;
    cin >> Q;
    bool exist[N] = {};
    DEBUG(nodes, sum, cost_to_parent);
    while(Q--) {
        ll k;
        cin >> k;
        priority_queue<ll, V<ll>, function<ll(ll, ll)>> pq([&](ll a, ll b) { return hld.decomposed_id[a] < hld.decomposed_id[b]; });
        for(ll i = 0; i < k; i++) {
            ll e;
            cin >> e;
            pq.push(e);
            exist[e] = true;
        }

        ll ans = 0;

        DEBUG(k);

        while(1 < pq.size()) {
            ll n1 = pq.top();
            pq.pop();
            exist[n1] = false;
            ll n2 = pq.top();
            DEBUG(make_tuple(n1, n2));
            if(hld.component_id[n1] != hld.component_id[n2]) {
                ll head = hld.head[n1];
                DEBUG(make_tuple(head, n1, n2, hld.decomposed_id[n1], hld.decomposed_id[n2]));
                ll parent = hld.parent_node_idx[head];
                ll n1_id = hld.decomposed_id[n1];
                ll head_id = hld.decomposed_id[head];
                // DEBUG(make_tuple(head_id, n1, hld.head[n1], sum[head_id]-sum[n1], cost_to_parent[head]));
                ans += sum[n1_id] - sum[head_id];
                ans += cost_to_parent[head];
                if(parent != -1 && !exist[parent]) {
                    DEBUG(parent);
                    pq.push(parent);
                    exist[parent] = true;
                }
            } else {
                ll id1 = hld.decomposed_id[n1];
                ll id2 = hld.decomposed_id[n2];
                // DEBUG(make_tuple(id1, id2));
                ans += sum[id1] - sum[id2];
            }
        }

        exist[pq.top()] = false;
        
        cout << ans << endl << flush;
    }
    return 0;
}
0