제출 #1369450

#제출 시각아이디문제언어결과실행 시간메모리
1369450c12경주 (Race) (IOI11_race)C++20
100 / 100
222 ms35596 KiB
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 200005;
const int MAXK = 1000005;
const int INF = 1e9;

// Global state for Centroid Decomposition
vector<pair<int, int>> adj[MAXN];
int sz[MAXN], vis[MAXN];
int mn_ans;
int K_val;

// Lookup table for minimum edges for a given distance
int min_edges[MAXK]; 

// Rollback buffers to avoid O(K) memset
int rollback_list[MAXN]; 
int rollback_ptr = 0;

// Buffer for current subtree nodes
pair<int, int> subtree_nodes[MAXN];
int subtree_ptr = 0;

void get_size(int u, int p) {
    sz[u] = 1;
    for (auto &edge : adj[u]) {
        int v = edge.first;
        if (v != p && !vis[v]) {
            get_size(v, u);
            sz[u] += sz[v];
        }
    }
}

int get_centroid(int u, int p, int total_n) {
    for (auto &edge : adj[u]) {
        int v = edge.first;
        if (v != p && !vis[v] && sz[v] > total_n / 2) {
            return get_centroid(v, u, total_n);
        }
    }
    return u;
}

void dfs_collect(int u, int p, int depth, int cost) {
    if (cost > K_val) return;
    
    subtree_nodes[subtree_ptr++] = {depth, cost};
    
    for (auto &edge : adj[u]) {
        int v = edge.first;
        if (v != p && !vis[v]) {
            dfs_collect(v, u, depth + 1, cost + edge.second);
        }
    }
}

void solve(int u) {
    get_size(u, -1);
    int cen = get_centroid(u, -1, sz[u]);
    vis[cen] = 1;

    rollback_ptr = 0;
    min_edges[0] = 0;
    rollback_list[rollback_ptr++] = 0;

    for (auto &edge : adj[cen]) {
        int v = edge.first;
        if (vis[v]) continue;

        subtree_ptr = 0;
        dfs_collect(v, cen, 1, edge.second);

        // Step 1: Query - Match current branch nodes against previous branches
        for (int i = 0; i < subtree_ptr; i++) {
            int d = subtree_nodes[i].second;
            int e = subtree_nodes[i].first;
            if (K_val >= d && min_edges[K_val - d] != INF) {
                mn_ans = min(mn_ans, e + min_edges[K_val - d]);
            }
        }

        // Step 2: Merge - Add current branch nodes to the lookup table
        for (int i = 0; i < subtree_ptr; i++) {
            int d = subtree_nodes[i].second;
            int e = subtree_nodes[i].first;
            if (d <= K_val) {
                if (min_edges[d] == INF) rollback_list[rollback_ptr++] = d;
                min_edges[d] = min(min_edges[d], e);
            }
        }
    }

    // Rollback distances used by this centroid
    for (int i = 0; i < rollback_ptr; i++) {
        min_edges[rollback_list[i]] = INF;
    }

    // Recurse to subtrees
    for (auto &edge : adj[cen]) {
        if (!vis[edge.first]) {
            solve(edge.first);
        }
    }
}

int best_path(int N, int K, int H[][2], int L[]) {
    // Reset global state for each call [cite: 130, 131]
    K_val = K;
    mn_ans = INF;
    rollback_ptr = 0;
    subtree_ptr = 0;

    for (int i = 0; i < N; i++) {
        adj[i].clear();
        vis[i] = 0;
        sz[i] = 0;
    }
    
    // Using a loop for the large K array to ensure it is fully initialized
    for (int i = 0; i < MAXK; i++) {
        min_edges[i] = INF;
    }

    // Build the highways network [cite: 17, 18, 19]
    for (int i = 0; i < N - 1; i++) {
        adj[H[i][0]].push_back({H[i][1], L[i]});
        adj[H[i][1]].push_back({H[i][0], L[i]});
    }

    solve(0);

    // Return the minimum highways or -1 if no valid course exists [cite: 21]
    return (mn_ans >= INF) ? -1 : mn_ans;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…