我也就只会做做板题了…
记得清零数组的时候子树遍历清零,否则会T
CODE
#include<bits/stdc++.h>
using namespace std;
inline void read(int &num) {
char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg = -flg;
for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar()); num*=flg;
}
const int MAXN = 200005;
const int MAXK = 1000005;
int n, k, fir[MAXN], cnt;
struct edge { int to, nxt, w; }e[MAXN<<1];
inline void link(int u, int v, int ww) {
e[++cnt] = (edge){ v, fir[u], ww }, fir[u] = cnt;
}
bool ban[MAXN];
int Get_Size(int x, int ff) {
int re = 1;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to] && v != ff) re += Get_Size(v, x);
return re;
}
int Get_Root(int x, int ff, int Size, int &G) {
int re = 1; bool flg = true;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to] && v != ff) {
int temp = Get_Root(v, x, Size, G); re += temp;
if(temp<<1 > Size) flg = 0;
}
if(Size-re<<1 > Size) flg = 0;
if(flg) G = x;
return re;
}
int st[MAXN][2], top, Ans;
void Count(int x, int ff, int dep, int dis) {
if(dis > k) return;
++top, st[top][0] = dep, st[top][1] = dis;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to] && v != ff)
Count(v, x, dep+1, dis+e[i].w);
}
int f[MAXK];
void Clear(int x, int ff, int dis) {
if(dis > k) return;
f[dis] = n;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to] && v != ff)
Clear(v, x, dis+e[i].w);
}
inline void Solve(int x) {
f[0] = 0;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to]) {
Count(v, x, 1, e[i].w);
for(int j = 1; j <= top; ++j)
Ans = min(Ans, st[j][0] + f[k-st[j][1]]);
while(top) f[st[top][1]] = min(f[st[top][1]], st[top][0]), --top;
}
Clear(x, 0, 0);
}
int TDC(int x) {
int Size = Get_Size(x, 0);
Get_Root(x, 0, Size, x);
Solve(x); ban[x] = 1;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to]) TDC(v);
}
int main() {
read(n), read(k); Ans = n;
for(int i = 1, x, y, z; i < n; ++i)
read(x), read(y), read(z), link(x+1, y+1, z), link(y+1, x+1, z);
for(int i = 1; i <= k; ++i) f[i] = n;
TDC(1);
printf("%d
", Ans < n ? Ans : -1);
}