RT,本题我使用 dsu on tree 算法,获得了 90 pts 的好成绩,有没有神仙路过救救孩子/kel
https://www.luogu.com.cn/record/46782252
#include<cstdio>
#include<map>
const int inf=0x3f3f3f3f;
typedef long long ll;
int Rt,Son;
int cnt,lim,ans=inf;
std::map<ll,int> buc;
ll sum[200005];
int h[200005],to[400005],ver[400005],w[400005];
int dep[200005],size[200005],son[200005];
inline int read() {
register int x=0,f=1;register char s=getchar();
while(s>'9'||s<'0') {if(s=='-') f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
return x*f;
}
inline int min(const int &x,const int &y) {return x<y? x:y;}
inline void add(int x,int y,int z) {to[++cnt]=y;ver[cnt]=h[x];w[cnt]=z;h[x]=cnt;}
inline void dfs1(int x,int fa) {
size[x]=1;
for(register int i=h[x];i;i=ver[i]) {
int y=to[i]; if(y==fa) continue;
dep[y]=dep[x]+1; sum[y]=sum[x]+w[i];
dfs1(y,x); size[x]+=size[y];
if(size[son[x]]<size[y]) son[x]=y;
}
}
inline void upd(int x,int fa,int d) {
//sum[x]-sum[Rt]+(sum[y_1]-sum[Rt])=lim
//printf("%d %d %d %d %d %d %d %d %d\n",tmp,Rt,sum[Rt],sum[x]-sum[Rt],buc[tmp],dep[Rt],dep[x],buc[tmp]-dep[Rt]+dep[x]-dep[Rt]);
ll tmp=lim-(sum[x]-sum[Rt])+sum[Rt];
if(d>0) {
if(tmp>0&&buc.find(tmp)!=buc.end()) {ans=min(ans,buc[tmp]-dep[Rt]+dep[x]-dep[Rt]);}
}
for(register int i=h[x];i;i=ver[i]) {
int y=to[i]; if(y==fa||y==Son) continue;
upd(y,x,d);
}
if(d>0) {if(buc.find(sum[x])==buc.end()) buc[sum[x]]=dep[x]; else buc[sum[x]]=min(buc[sum[x]],dep[x]);}
else {buc.erase(sum[x]);}
}
inline void dfs2(int x,int fa,int opt) {
for(register int i=h[x];i;i=ver[i]) {
int y=to[i]; if(y==fa||y==son[x]) continue;
dfs2(y,x,0);
}
if(son[x]) dfs2(son[x],x,1),Son=son[x];
Rt=x; upd(x,fa,1); Son=0;
if(!opt) upd(x,fa,-1);
}
int main() {
freopen("P4149_3.in","r",stdin);
int n=read(); lim=read();
for(register int i=1;i<n;++i) {
int x=read()+1,y=read()+1,z=read();
add(x,y,z); add(y,x,z);
}
dfs1(1,-1); dfs2(1,-1,0);
if(ans==0x3f3f3f3f) printf("-1\n");
else printf("%d\n",ans);
return 0;
}