2429: [HAOI2006]聪明的猴子

感觉回到了NOIP水平。

最小生成树有一个性质就是最小生成树必为最小瓶颈生成树,即最大边的边权最小(从kruskal算法的构造过程很容易看出这点,毕竟是从小到大加边),于是此题很水,MST求完后最后加的那条边就是树上的最大边,用每个猴子的半径比一下就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1000+5;
struct Edge{
	int u,v;
	double w;
	bool operator<(const Edge &rhs)const{
		return w<rhs.w;
	}
}e[N*N];
inline int read(){
	int x=0,f=1;char ch;
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int x[N],y[N];
inline double sqr(double x){return x*x;}
inline double dist(int i,int j){
	return sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
}
int pa[N],r[N],m,n,cnt;
int findset(int x){
	return pa[x]!=x?pa[x]=findset(pa[x]):x;
}
double MST(){
	for(int i=1;i<=n;i++)pa[i]=i;
	sort(e+1,e+1+cnt);
	int tot=0;
	for(int i=1;i<=cnt;i++){
		int u=findset(e[i].u),v=findset(e[i].v);
		if(u!=v){
			pa[u]=v;
			tot++;
			if(tot==n-1)return e[i].w;
		}
	}
}
int main(){
	m=read();
	for(int i=1;i<=m;i++)r[i]=read();
	n=read();
	for(int i=1;i<=n;i++)x[i]=read(),y[i]=read();
	for(int i=1;i<=n;i++)
	for(int j=i+1;j<=n;j++){
		cnt++;
		e[cnt].u=i;e[cnt].v=j;e[cnt].w=dist(i,j);
	}
	double limit=MST();
	int ans=0;
	for(int i=1;i<=m;i++)
	if(r[i]>=limit)ans++;
	printf("%d",ans);
	return 0;
}



你可能感兴趣的:(2429: [HAOI2006]聪明的猴子)