题目大意:在坐标轴的第一象限有个点,给定,和点的扩散速度(按圆形扩散,范围相交视为在同一连通块上),给定个询问,询问时间为时连通块的数量

分析:不妨将每个点两两连边,边的权值为两点成为同一连通块的时间,可以发现此时问题便转化成求这张图的最小生成树类的问题,求出连通块数量减少时的时间。对于问题采用离线处理,易求出答案

参考代码:

#define LL long long
using namespace std;
const int M=1005;

int n,q;
struct Edge{
	int u,v;
	double w,tim;
}e[M*M];
struct Node{
	int val,id,anq;
}ask[M];
int fa[M],x[M],y[M],vv[M];
double timset[M];

int findfa(int x){
	if(fa[x]==x) return x;
	return fa[x]=findfa(fa[x]);
}



bool Cmp(Edge u1,Edge v1){
	return u1.tim<v1.tim;
}


bool Cmp2(Node u2,Node v2){
	return u2.val<v2.val;
} 

bool Cmp3(Node u3,Node v3){
	return u3.id<v3.id;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&x[i],&y[i],&vv[i]);
		fa[i]=i;
	}
	scanf("%d",&q);
	for(int i=1;i<=q;i++){
		scanf("%d",&ask[i].val);
		ask[i].id=i;
	}
	sort(ask+1,ask+1+q,Cmp2);
	int cnt=0;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			e[++cnt].u=i; e[cnt].v=j; e[cnt].w=1.0*sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+1.0*(y[i]-y[j])*(y[i]-y[j]));
	        e[cnt].tim=1.0*e[cnt].w/(1.0*vv[i]+1.0*vv[j]);
	        //cout<<"G"<<e[cnt].w<<"\n";
			//cout<<"T"<<e[cnt].tim<<" ";
		}
	}
	int num=n,tot=1;
	timset[0]=0;
	sort(e+1,e+1+cnt,Cmp);
	for(int i=1;i<=cnt;i++){
		int lfa=findfa(e[i].u);
		int rfa=findfa(e[i].v);
		if(lfa!=rfa){
			timset[tot]=e[i].tim; tot++;
			fa[lfa]=rfa; num--;
		}
	}
	//for(int i=1;i<=tot;i++) cout<<timset[i]<<" ";	
	tot=1;
	for(int i=1;i<=q;i++)
	{   
	    while(ask[i].val>=timset[tot]&&tot<n){
			tot++;
			
		}
		ask[i].anq=n-(tot-1);
	}
	sort(ask+1,ask+1+q,Cmp3);
	for(int i=1;i<=q;i++){
	printf("%d\n",ask[i].anq);
	}
}