洛谷P2504
题目大概意思是给n个树,都给出坐标,m个猴子,每个猴子的最大跳跃距离也给出,问有多少只猴子可以在这n棵树之间自由穿梭。
kruskal解法
计算出每两棵树之间的距离并建边,把所有边按照长度从小到大排序,遍历每条边,当连通块数量只剩一个的时候,就跳出,并且记录下访问的最后一条边的长度,用这个长度去和猴子的跳跃距离作比较即可。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double EPS=1e-6;
typedef long long ll;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int monkey[N],fa[N];
struct tree
{
int x,y;
}t[N];
struct node
{
int from,to;double dis;
}e[1000050];
int tot=0;
void addedge(int u,int v)
{
tot++;
e[tot].from=u;
e[tot].to=v;
e[tot].dis=sqrt((t[u].x-t[v].x)*(t[u].x-t[v].x)+(t[u].y-t[v].y)*(t[u].y-t[v].y));
}
bool cmp(node a,node b)
{
return a.dis<b.dis;
}
int finds(int x)
{
if(fa[x]==x)
return x;
return fa[x]=finds(fa[x]);
}
int main()
{
IOS;
// freopen("monkey.in","r",stdin);
// freopen("monkey.out","w",stdout);
int m;
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>monkey[i];
}
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>t[i].x>>t[i].y;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i!=j)
addedge(i,j);
}
}
sort(e+1,e+tot+1,cmp);
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
int cnt=n;
double maxd=0;
for(int i=1;i<=tot;i++)
{
if(cnt==1)
break;
int xx=finds(e[i].from);
int yy=finds(e[i].to);
if(xx!=yy)
{
fa[xx]=yy;
cnt--;
maxd=e[i].dis;
}
}
int ans=0;
for(int i=1;i<=m;i++)
{
if(maxd<=monkey[i])
{
ans++;
}
}
cout<<ans;
}