Problem
给定一棵树,边有边权,定义两点之间距离为两点路径上的最小值。
Q
Q
Q 次询问,每次询问
k
i
、
v
i
k_i、v_i
ki、vi,问从
v
i
v_i
vi 出发到达每个点时,距离大于等于
k
i
k_i
ki 的点有多少个
Solution
将边权、询问中的
k
i
k_i
ki 从大到小排序。
每次将边连起来,并查集合并。
询问中,与此点联通的点的个数即为答案
Code
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
int n,m,sz[N],fa[N],ans[N];
struct node{int x,y,z;}a[N],q[N];
inline bool cmp(node x,node y){return x.z>y.z;}
int find(int x){
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) fa[i]=i,sz[i]=1;
for(int i=1;i<n;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
for(int i=1;i<=m;i++) scanf("%d%d",&q[i].z,&q[i].x),q[i].y=i;
sort(a+1,a+n,cmp);sort(q+1,q+m+1,cmp);
int tmp=1;
for(int i=1;i<=m;i++){
while(tmp<n && a[tmp].z>=q[i].z){
int x=find(a[tmp].x),y=find(a[tmp].y);
if(x!=y) fa[x]=y,sz[y]+=sz[x];
tmp++;
}
ans[q[i].y]=sz[find(q[i].x)]-1;
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}