제출 #1276686

#제출 시각아이디문제언어결과실행 시간메모리
1276686iustinmircea10Museum (CEOI17_museum)C++17
20 / 100
3103 ms455156 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = (ll)9e18;

int n, k, start_node;
vector<vector<pair<int,int>>> adj; // 0-based

// dp[u][s] = vector of candidate (time, dist) pairs for visiting s nodes in subtree(u)
// time = total walking time, dist = distance from u to last visited node in that candidate
vector<vector<vector<pair<ll,ll>>>> dp;

static inline void prune_vec(vector<pair<ll,ll>> &v) {
    if (v.empty()) return;
    sort(v.begin(), v.end(), [](const pair<ll,ll>&a, const pair<ll,ll>&b){
        if (a.first != b.first) return a.first < b.first;
        return a.second < b.second;
    });
    // compress equal times, keep minimal dist
    vector<pair<ll,ll>> tmp;
    tmp.reserve(v.size());
    for (auto &p : v) {
        if (tmp.empty() || p.first != tmp.back().first) tmp.push_back(p);
        else if (p.second < tmp.back().second) tmp.back().second = p.second;
    }
    // keep non-dominated: times increasing, keep only pairs with strictly smaller dist than any kept before
    vector<pair<ll,ll>> kept;
    kept.reserve(tmp.size());
    ll best_dist = INF;
    for (auto &p : tmp) {
        if (p.second < best_dist) {
            kept.push_back(p);
            best_dist = p.second;
        }
    }
    v.swap(kept);
}

void dfs(int u, int p) {
    dp[u].clear();
    dp[u].resize(2);
    dp[u][0].push_back({0,0}); // visiting 0 nodes
    dp[u][1].push_back({0,0}); // visiting only u: time 0, dist 0

    for (auto [v, w] : adj[u]) {
        if (v == p) continue;
        dfs(v, u);

        int a_sz = (int)dp[u].size();
        int b_sz = (int)dp[v].size();
        int new_sz = a_sz + b_sz - 1;
        vector<vector<pair<ll,ll>>> newdp(new_sz);

        // copy old dp[u] (cases where we don't take anything from v)
        for (int i = 0; i < a_sz; ++i) {
            newdp[i].insert(newdp[i].end(), dp[u][i].begin(), dp[u][i].end());
        }

        // combine: i from u, j from v (both >= 1)
        for (int i = 1; i < a_sz; ++i) {
            for (int j = 1; j < b_sz; ++j) {
                int newk = i + j;
                // combine every candidate pair from dp[u][i] and dp[v][j]
                for (auto &A : dp[u][i]) {
                    for (auto &B : dp[v][j]) {
                        // u-first then v: must return from A's endpoint to u, go to v, do B (starting at v)
                        ll t1 = A.first + A.second + w + B.first;
                        ll d1 = B.second + w; // new endpoint distance from u
                        newdp[newk].push_back({t1, d1});

                        // v-first then u: go to v, do B, return to u, then do A
                        ll t2 = w + B.first + B.second + w + A.first;
                        ll d2 = A.second; // endpoint remains as in A
                        newdp[newk].push_back({t2, d2});
                    }
                }
            }
        }

        // prune each newdp[k] to keep only Pareto-optimal states
        for (int t = 0; t < new_sz; ++t) {
            prune_vec(newdp[t]);
        }

        dp[u].swap(newdp);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> k >> start_node;
    --start_node; // convert to 0-based
    adj.assign(n, {});
    for (int i = 1; i < n; ++i) {
        int u,v,w; cin >> u >> v >> w; --u; --v;
        adj[u].push_back({v,w});
        adj[v].push_back({u,w});
    }
    dp.assign(n, {});
    dfs(start_node, -1);

    if (k >= (int)dp[start_node].size()) {
        cout << "-1\n"; // or handle accordingly if impossible
        return 0;
    }
    // answer is minimal 'time' among candidates for dp[start][k]
    ll ans = INF;
    for (auto &p : dp[start_node][k]) ans = min(ans, p.first);
    cout << ans << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...