D129 最小生成树 Kruskal 算法 P2504 [HAOI2006] 聪明的猴子

D129 最小生成树 Kruskal 算法 P2504 [HAOI2006] 聪明的猴子_哔哩哔哩_bilibili

 

P2504 [HAOI2006] 聪明的猴子 - 洛谷

给定 M 个猴子的最大跳跃距离,N 棵树的坐标,统计有多少个猴子可以跳到所有树上。

思路

把任意两颗树之间的距离算出来,做边权

跑 Kruskal 算法找最小生成树,加边的同时记录下最大的边权 $mxd$

枚举每个猴的跳跃距离,如果跳跃距离 $\ge mxd$,就 $ans++$

相关板子:

D08【模板】最小生成树 Kruskal 算法 - 董晓 - 博客园

 

// 最小生成树 Kruskal算法 O(NlogN)
#include<bits/stdc++.h>
using namespace std;

const int N=1e6+5;
int n,m,k,tot,ans;
int d[N],x[N],y[N],fa[N];
double mxd;
pair<double,pair<int,int> >e[N]; //边集

int find(int u){ //并查集的找根
  return fa[u]==u?u:fa[u]=find(fa[u]);
}
void kruskal(){
  sort(e+1,e+k+1); //排序
  for(int i=1; i<=n; i++) fa[i]=i;
  for(int i=1; i<=k; i++){
    int x=find(e[i].second.first),y=find(e[i].second.second);
    if(x!=y){
      fa[x]=y;
      mxd=e[i].first; //最大边权
      if(++tot==n-1) break;
    }
  }
  for(int i=1; i<=m; i++)if(d[i]>=mxd)ans++;
  cout<<ans;
}
int main(){
  cin>>m; //m个猴
  for(int i=1; i<=m; i++) cin>>d[i];
  cin>>n; //n颗树
  for(int i=1; i<=n; i++) cin>>x[i]>>y[i];
  for(int i=1; i<=n; i++)for(int j=1; j<=n; j++)if(i!=j){
    e[++k]={sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])),{i,j}};
  }
  
  kruskal();
}

 

posted @ 2026-04-13 15:20  董晓  阅读(108)  评论(0)    收藏  举报