「IOI2011」Race 发表于 2019-03-05 | 分类于 点分治 | | 浏览量: 次 又是一个赤裸裸的点分治QwQ。 传送门洛谷P4149 BZOJ2599 题解基本上就是点分治的裸题QwQ。 每次找重心,然后刷出当前处理的子树中每个点到重心的距离和经过的边的数量,直接搞就行了,记得要刷边数的最小值,还要判无解。没啥好说的QwQ。 代码12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667#include<cstdio>#include<cstring>using namespace std;const int maxn=200005,maxk=1000005,inf=0x3F3F3F3F;int n,K,tot,lnk[maxn],son[maxn*2],w[maxn*2],nxt[maxn*2],sum,siz[maxn],maxp[maxn],rt,dist[maxn],cnt[maxn],num,Q[maxn][2],ans=inf,jud[maxk],que[maxn];bool vis[maxn];inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return ret*f;}inline void add_e(int x,int y,int z){tot++;son[tot]=y;w[tot]=z;nxt[tot]=lnk[x];lnk[x]=tot;}void GetRoot(int now,int fa){ siz[now]=1;maxp[now]=0; for(int i=lnk[now];i;i=nxt[i]) { if(vis[son[i]]||son[i]==fa) continue; GetRoot(son[i],now);siz[now]+=siz[son[i]]; if(siz[son[i]]>maxp[now]) maxp[now]=siz[son[i]]; } if(sum-siz[now]>maxp[now]) maxp[now]=sum-siz[now]; if(maxp[now]<maxp[rt]) rt=now;}void GetDist(int now,int fa){ if(dist[now]>K||cnt[now]>ans) return; num++;Q[num][0]=dist[now];Q[num][1]=cnt[now]; for(int i=lnk[now];i;i=nxt[i]) if(!vis[son[i]]&&son[i]!=fa) {dist[son[i]]=dist[now]+w[i];cnt[son[i]]=cnt[now]+1;GetDist(son[i],now);}}void Solve(int now){ int len=1;que[1]=0;vis[now]=true;jud[0]=0; for(int i=lnk[now];i;i=nxt[i]) { if(vis[son[i]]) continue; num=0;dist[son[i]]=w[i];cnt[son[i]]=1;GetDist(son[i],0); for(int j=1;j<=num;j++) if(Q[j][1]+jud[K-Q[j][0]]<ans) ans=Q[j][1]+jud[K-Q[j][0]]; for(int j=1;j<=num;j++) { if(Q[j][1]<jud[Q[j][0]]) jud[Q[j][0]]=Q[j][1]; que[++len]=Q[j][0]; } } for(int i=1;i<=len;i++) jud[que[i]]=inf; for(int i=lnk[now];i;i=nxt[i]) if(!vis[son[i]]) {sum=siz[son[i]];rt=0;GetRoot(son[i],0);Solve(rt);}}int main(){ n=read();K=read(); for(int i=1;i<n;i++) { int a=read()+1,b=read()+1,c=read(); add_e(a,b,c);add_e(b,a,c); } memset(jud,63,sizeof(jud)); maxp[0]=sum=n;GetRoot(1,0);Solve(rt); printf("%d\n",ans==inf?-1:ans); return 0;}