「IOI2011」Race

又是一个赤裸裸的点分治QwQ。

传送门

洛谷P4149

BZOJ2599

题解

基本上就是点分治的裸题QwQ。

每次找重心,然后刷出当前处理的子树中每个点到重心的距离和经过的边的数量,直接搞就行了,记得要刷边数的最小值,还要判无解。没啥好说的QwQ。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#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;
}