[BZOJ2599]Race
Posted jefflyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ2599]Race相关的知识,希望对你有一定的参考价值。
假设当前分治到$x$,记$t_i$为到$x$距离为$i$的点中,到$x$最少的边数,那么我们采用分治2:每次统计一个儿子与集合中点产生的贡献,并把儿子信息合并到集合中,假设当前统计到$u$,$u$到$x$的边数为$d$,那么用$d+t_{k-dis_{x,u}}$更新答案即可,注意最后重置$t_i$时要遍历子树而不是memset,不然无法保证复杂度
#include<stdio.h> const int inf=100000000; int min(int a,int b){return a<b?a:b;} int max(int a,int b){return a>b?a:b;} int h[200010],to[400010],nex[400010],w[400010],M; void add(int a,int b,int c){ M++; to[M]=b; w[M]=c; nex[M]=h[a]; h[a]=M; } bool v[200010]; int siz[200010],n; void dfs1(int fa,int x){ n++; siz[x]=1; for(int i=h[x];i;i=nex[i]){ if(!v[to[i]]&&to[i]!=fa){ dfs1(x,to[i]); siz[x]+=siz[to[i]]; } } } int mn,cn; void dfs2(int fa,int x){ int i,k; k=0; for(i=h[x];i;i=nex[i]){ if(!v[to[i]]&&to[i]!=fa){ dfs2(x,to[i]); k=max(k,siz[to[i]]); } } k=max(k,n-siz[x]); if(k<mn){ mn=k; cn=x; } } int t[1000010],k,ans; void dfs3(int fa,int x,int dep,int dis){ if(dis<=k)ans=min(ans,dep+t[k-dis]); for(int i=h[x];i;i=nex[i]){ if(!v[to[i]]&&to[i]!=fa)dfs3(x,to[i],dep+1,dis+w[i]); } } void dfs4(int fa,int x,int dep,int dis){ if(dis<=k)t[dis]=min(t[dis],dep); for(int i=h[x];i;i=nex[i]){ if(!v[to[i]]&&to[i]!=fa)dfs4(x,to[i],dep+1,dis+w[i]); } } void dfs5(int fa,int x,int dis){ if(dis<=k)t[dis]=inf; for(int i=h[x];i;i=nex[i]){ if(!v[to[i]]&&to[i]!=fa)dfs5(x,to[i],dis+w[i]); } } void solve(int x){ int i; n=0; dfs1(0,x); mn=inf; dfs2(0,x); x=cn; t[0]=0; for(i=h[x];i;i=nex[i]){ if(!v[to[i]]){ dfs3(x,to[i],1,w[i]); dfs4(x,to[i],1,w[i]); } } dfs5(0,x,0); v[x]=1; for(i=h[x];i;i=nex[i]){ if(!v[to[i]])solve(to[i]); } } int main(){ int n,i,a,b,c; scanf("%d%d",&n,&k); for(i=1;i<n;i++){ scanf("%d%d%d",&a,&b,&c); a++; b++; add(a,b,c); add(b,a,c); } for(i=0;i<=k;i++)t[i]=inf; ans=inf; solve(1); if(ans==inf)ans=-1; printf("%d",ans); }
以上是关于[BZOJ2599]Race的主要内容,如果未能解决你的问题,请参考以下文章