# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
108679 | crackersamdjam | Race (IOI11_race) | C++14 | 0 ms | 0 KiB |
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
#define gc getchar_unlocked()
#define pc(x) putchar_unlocked(x)
template<typename T> void scan(T &x){x = 0;register bool _=0;register T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void print(T n){register bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);pc(10);}
template<typename First, typename ... Ints>
void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
using namespace std;
typedef pair<int, int> pii;
const int MM = 2e5+2;
int N, K, dis[MM], sz[MM], tot, len[MM], ans = INT_MAX;
bool vis[MM];
vector<pii> adj[MM];
unordered_map<int, int> cnt;
int getsz(int cur, int pre){
sz[cur] = 1;
for(auto &e: adj[cur]){
if(e.first != pre && !vis[e.first])
sz[cur] += getsz(e.first, cur);
}
return sz[cur];
}
int findcent(int cur, int pre){
for(auto &e: adj[cur]){
if(!vis[e.first] && e.first != pre && sz[e.first]*2 > tot)
return findcent(e.first, cur);
}
return cur;
}
void dfs(int cur, int pre){
for(auto &e: adj[cur]){
if(e.first == pre || vis[e.first])
continue;
dis[e.first] = dis[cur] + e.second;
len[e.first] = len[cur] + 1;
dfs(e.first, cur);
}
//printf("add %d %d %d\n", cur, dis[cur], len[cur]);
if(!cnt[dis[cur]])
cnt[dis[cur]] = len[cur];
else
cnt[dis[cur]] = min(cnt[dis[cur]], len[cur]);
}
void go(int root){
//printf("go %d\n", root);
//works bc root is edge of tree
//first time must start from endpt
getsz(root, -1);
tot = sz[root];
if(sz[root] == 1)
return;
int cent = findcent(root, -1);
//printf("cent %d\n", cent);
cnt.clear();
dis[cent] = 0;
len[cent] = 0;
dfs(cent, -1);
for(auto u: cnt){
//printf("u %d %d\n", u.first, u.second);
if(u.first <= K and (cnt[K-u.first] or (u.first == K and cnt[K])))
ans = min(ans, u.second + cnt[K-u.first]);
}
vis[cent] = 1;
//block off
for(auto u: adj[cent]){
if(!vis[u.first])
go(u.first);
}
}
int best_path(int n, int k, int h[][2], int l[]){
N = n, K = k;
cout << n << " " << k << endl;
for(int i = 0; i < N-1; i++){
cout << h[i][0] << " " << h[i][1] << " " << l[i] << endl;
adj[h[i][0]].push_back({h[i][1], l[i]});
adj[h[i][1]].push_back({h[i][0], l[i]});
}
for(int i = 0; i < N; i++){
if(adj[i].size() == 1){
go(i);
break;
}
}
cout << ans << endl;
return (ans == INT_MAX? -1: ans);
}
#ifndef ONLINE_JUDGE
int main(){
int h[][2] = {{0, 1}, {1, 2}, {1, 3}};
int l[] = {1, 2, 4};
int out = best_path(4, 3, h, l);
print(out);
return 0;
/*
int h[][2] = {{0, 1}, {1, 2}};
int l[] = {1, 1};
int out = best_path(3, 3, h, l);
print(out == INT_MAX? -1: out);
return 0;
*/
/*
int h[][2] = {{0, 1}, {0, 2}, {2, 3}, {3, 4}, {4, 5}, {0, 6}, {6, 7}, {6, 8}, {8, 9}, {8, 10}};
int l[] = {3, 4, 5, 4, 6, 3, 2, 5, 6, 7};
int out = best_path(11, 12, h, l);
print(out == INT_MAX? -1: out);
return 0;
*/
}
#endif
/*
*
* centroid decomp with map storing lengths from centroid (and min #)
* check if two paths sum to K - linear
* n log n
*/