Mootube

  • 给出一棵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,果然我还是最喜欢逍遥子一些

原文地址:https://www.cnblogs.com/lsyyy/p/11261018.html