BZOJ 2599: [IOI2011]Race
点分治模板
#include<cstdio> #include<algorithm> using namespace std; int cnt,n,K,ans,N,root,F_top,last[1000005],sz[1000005],F_[1000005],vis[1000005],F_stack[1000005],G_stack[1000005],F[1000005],G[1000005]; struct node{ int to,next,val; }e[1000005]; void add(int a,int b,int c){ e[++cnt].to=b; e[cnt].next=last[a]; e[cnt].val=c; last[a]=cnt; } void find_root(int x,int fa){ sz[x]=1,F_[x]=0; for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (V==fa || vis[V]) continue; find_root(V,x); sz[x]+=sz[V]; F_[x]=max(F_[x],sz[V]); } F_[x]=max(F_[x],N-sz[x]); if (F_[x]<F_[root]) root=x; } void get_dis(int x,int fa,int val,int dep){ sz[x]=1; if (val==K) ans=min(ans,dep); if (val<=K) F_stack[++F_top]=val; if (val<=K) F[val]=min(F[val],dep); for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (vis[V] || V==fa) continue; get_dis(V,x,val+e[i].val,dep+1); sz[x]+=sz[V]; } } void solve(int x){ int G_top=0; for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (vis[V]) continue; F_top=0; get_dis(V,x,e[i].val,1); for (int j=1; j<=F_top; j++) ans=min(ans,F[F_stack[j]]+G[K-F_stack[j]]); for (int j=1; j<=F_top; j++) G[F_stack[j]]=min(G[F_stack[j]],F[F_stack[j]]),F[F_stack[j]]=1e9,G_stack[++G_top]=F_stack[j]; } for (int i=1; i<=G_top; i++) G[G_stack[i]]=1e9; } void divide(int x){ vis[x]=1; solve(x); for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (vis[V]) continue; N=sz[V],root=0; find_root(V,x); divide(root); } } int main(){ scanf("%d%d",&n,&K); for (int i=1; i<n; i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); x++,y++; add(x,y,z); add(y,x,z); } for (int i=1; i<=K; i++) F[i]=G[i]=1e9; ans=1e9; N=n,root=0; F_[0]=1e9; find_root(1,0); divide(root); if (ans!=1e9) printf("%d\n",ans); else printf("-1\n"); return 0; }