Submission #736507

#TimeUsernameProblemLanguageResultExecution timeMemory
736507Skywk경주 (Race) (IOI11_race)C++17
0 / 100
11 ms20700 KiB
#include "race.h"
#include<bits/stdc++.h>

using namespace std;

const int MAXN = 2e5;
const int MAX = 1e6;
vector<pair<int, int>> graph[MAXN+1];

int sz[MAXN+1];
bitset<MAXN+1> usd;
int find_centroid(int root){
    function<void(int, int)> get_sz = [&](int v, int p){
        sz[v] = 1;
        for(auto [u, d] : graph[v]){
            if(usd[u] || u == p) continue;
            get_sz(u, v);
            sz[v] += sz[u];
        }
    };
    get_sz(root, -1);
    function<int(int, int)> dfs = [&](int v, int p){
        for(auto [u, d] : graph[v]){
            if(usd[u] || u == p) continue;
            if(sz[u] > sz[root]/2) return dfs(u, v);
        }
        return v;
    };
    return dfs(root, -1);
}
tuple<int, int, int, int> best[MAX+1];//best and second best edges to reach dist
int TRACK;// K
int ANS = INT32_MAX; // answer
void update(const int &root, int v, int p, int dist, int lvl){
    if(dist > TRACK) return;
    //update best values
    auto [l1, u1, l2, u2] = best[dist];
    if(l1 == -1 || lvl <= l1){
        l2 = l1, u2 = u1;
        l1 = lvl, u1 = root;
    }
    else{
        if(l2 == -1 || lvl < l2){
            l2 = lvl, u2 = root;
        }
    }
    best[dist] = {l1, u1, l2, u2};
    for(auto [u, d] : graph[v]){
        if(usd[u] || u == p) continue;
        update(root, u, v, dist + d, lvl+1);
    }
}
void calc(const int &root, int v, int p, int dist, int lvl){
    if(dist > TRACK) return;
    if(get<0>(best[TRACK - dist]) != -1){
        auto [l1, u1, l2, u2] = best[TRACK - dist];
        if(root == u1){
            if(l2 != -1){
                ANS = min(ANS, l2 + lvl);
            }
        }
        else ANS = min(ANS, l1 + lvl);
    }
    for(auto [u, d] : graph[v]){
        if(usd[u] || u == p) continue;
        calc(root, u, v, dist + d, lvl + 1);
    }
}
void clear(int v, int p, int dist){
    if(dist > TRACK) return;
    best[dist] = {-1, -1, -1, -1};
    for(auto [u, d] : graph[v]){
        if(usd[u] || u == p) continue;
        clear(u, v, dist + d);
    }
}
void centroid_decomposition(int root){
    function<void(int)> dfs = [&](int v){
        int c = find_centroid(v);
        usd[c] = 1;
        for(auto [u, d] : graph[c]){
            if(usd[u]) continue;
            dfs(u);
        }
        
        for(auto [u, d] : graph[c]){
            if(usd[u]) continue;
            update(u, u, c, d, 1);
        }
        if(get<0>(best[TRACK]) != -1){
            ANS = min(ANS, get<0>(best[TRACK]));
        }
        for(auto [u, d] : graph[c]){
            if(usd[u]) continue;
            calc(u, u, c, d, 1);
        }
        clear(c, -1, 0);
        usd[c] = 0;
    };
    dfs(root);
}

int best_path(int N, int K, int H[][2], int L[]){
    for(int i=0; i<N-1; i++){
        graph[H[i][0] + 1].push_back({H[i][1] + 1, L[i]});
        graph[H[i][1] + 1].push_back({H[i][0] + 1, L[i]});
    }
    TRACK = K;
    for(int i=0; i<=MAX; i++){
        best[i] = {-1, -1, -1, -1};
    }
    centroid_decomposition(1);
    return (ANS == INT32_MAX ? -1 : ANS);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...