- 给出一棵n个点的树及每条边的边权,定义任意两个点的熟悉度为连接这两个点的路径上边权的最小值。再给出Q个询问,每次询问给出数对(ki,vi),要求计算出有多少个节点与节点vi的熟悉度大于等于ki。
首先对K由大到小sort一下,再按K值加边(大于等于K),统计一下连通块大小就是了
没带权并查集那样麻烦
#include<bits/stdc++.h>
#define re return
#define ll long long
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
const int maxn=10e5+5;
using namespace std;
template<typename T>inline void rd(T&x)
{
char c;bool f=0;
while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
x=c^48;
while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
if(f)x=-x;
}
int n,que,fa[maxn],cnt[maxn],ans[maxn];
struct node{
int fr,to,val;
inline void add()
{
rd(fr),rd(to),rd(val);
}
bool operator<(node a)const
{
re val>a.val;
}
}e[maxn];
struct nide{
int k,v,id;
bool operator<(nide a)const
{
re k>a.k;
}
}q[maxn];
inline int find(int x)
{
re x==fa[x]?x:fa[x]=find(fa[x]);
}
int main()
{
freopen("in.txt","r",stdin);
rd(n);rd(que);
cnt[n]=1;fa[n]=n;
inc(i,1,n-1)e[i].add(),cnt[i]=1,fa[i]=i;
inc(i,1,que)rd(q[i].k),rd(q[i].v),q[i].id=i;
sort(e+1,e+n);
sort(q+1,q+que+1);
int top=1;
inc(i,1,que)
{
while(top<n&&e[top].val>=q[i].k){
int f1=find(e[top].fr),f2=find(e[top].to);
if(f1!=f2)fa[f1]=f2,cnt[f2]+=cnt[f1];
++top;
}
ans[q[i].id]=cnt[find(q[i].v)];
}
inc(i,1,que)
printf("%d
",ans[i]-1);
re 0;
}
人总归是要有些野心的,至于能不能实现就另当别论l,果然我还是最喜欢逍遥子一些