bzoj2599: [IOI2011]Race
阿新 • • 發佈:2018-07-01
getch 點分治 記得 void num AS IV 合並 code
題目鏈接
bzoj2599: [IOI2011]Race
題解
點分治,用t[k]表示子樹中距離root為k 的最小邊路徑
轉移時先與前邊子樹和合並更新答案,然後更新距離父節點最優值,這樣就保證不在同一子樹內了
每次分層的時候記得清除答案
代碼
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9' ){if(c == '-')f = -1;c = getchar(); }
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
#define INF 1000000007
const int maxn = 200007;
struct node {
int v,w,next;
} edge[maxn << 1];
int head[maxn],num;
inline void add_edge(int u,int v,int w) {
edge[++ num].v = v;edge[num].w = w;edge[num].next = head[u];head[u] = num;
}
int n,k,root;
bool vis[maxn];
int dis[maxn],son[maxn],f[maxn],deep[maxn],t[1000007],tot;
void get_root(int x,int fa) {
son[x] = 1;f[x] = 0;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v == fa || vis[v]) continue;
get_root(v,x);
son[x] += son[v]; f[x] = std::max(f[x],son[v]);
}
f[x] = std::max(tot - son[x],f[x]);
if(f[x] < f[root])root = x;
}
int ans = INF;
void calc(int x,int fa) {
if(dis[x] <= k) ans = std::min(ans,deep[x] + t[k - dis[x]]);
else return;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(vis[v] || edge[i].v == fa) continue;
deep[v] = deep[x] + 1;
dis[v] = dis[x] + edge[i].w;
calc(v,x);
}
}
void update(int x,int fa,bool ty) {
if(dis[x] <= k) {
if(ty)t[dis[x]] = std::min(t[dis[x]],deep[x]);
else t[dis[x]] = n;
}
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v != fa && !vis[v]) update(v,x,ty);
}
}
void sol(int x) {
vis[x] = 1; t[0] = 0;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(vis[v]) continue;
deep[v] = 1;dis[v] = edge[i].w;
calc(v,0);update(v,0,1);
}
for(int i = head[x];i;i = edge[i].next)
if(!vis[edge[i].v]) update(edge[i].v,0,0);
for(int i = head[x];i;i = edge[i].next) {
if(!vis[edge[i].v]) {
root = 0;
tot = son[edge[i].v];
get_root(edge[i].v,0); sol(root);
}
}
}
int main() {
n = read(),k = read();
for(int i = 1;i <= k;++ i) t[i] = n;
for(int u,v,w,i = 1;i < n;++ i) {
u = read() + 1,v = read() + 1,w = read();
add_edge(u,v,w); add_edge(v,u,w);
}
ans = tot = n;f[0] = n;
get_root(1,0);
sol(root);
printf("%d\n",ans == n ? -1 : ans);
return 0;
}
bzoj2599: [IOI2011]Race