BZOJ2429: [HAOI2006]聪明的猴子

思路:求出最小生成树上的最长边即可

注意:1.kruscal建边可以只连有向边 prim得连双向边 因为不知道谁先被更新

           2.求距离的平方 不算出实际距离 因为猴子的跳跃距离均为整数 反而保留了精度 

#include<iostream>
#include<cmath>
#include<cstring>//memset
using namespace std;
const int N=1000+5;
struct E{
    int to,next,w;
}e[N*N];
struct P{
    int x,y;
}p[N];
int cnt,bounce[505],head[N],d[N],vis[N],ma,n;
int dist(int i,int j){//不用开根号算出实际距离 反而保留了精度 
    return ((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)); 
}
void add(int u,int v){
    e[++cnt].to=v;
    e[cnt].next=head[u];
    e[cnt].w=dist(u,v);
    head[u]=cnt;
    e[++cnt].to=u;
    e[cnt].next=head[v];
    e[cnt].w=dist(u,v);
    head[v]=cnt;
}
void prim(int x){
    memset(d,0x3f,sizeof(d)); 
    d[x]=0;
    int min=1e9,pos;
    for(int i=1;i<=n;i++){
        min=1e9;
        for(int j=1;j<=n;j++)
         if(!vis[j]&&min>d[j]) min=d[j],pos=j;
        vis[pos]=1;
        ma=max(ma,min);
        for(int j=head[pos];j;j=e[j].next)
          if(!vis[e[j].to]&&d[e[j].to]>e[j].w) d[e[j].to]=e[j].w;
    }
}
int main(){
   int m,ans=0;
   cin>>m;
   for(int i=1;i<=m;i++)cin>>bounce[i];
   cin>>n;
   for(int i=1;i<=n;i++)cin>>p[i].x>>p[i].y;
   for(int i=1;i<=n;i++)
    for(int j=i+1;j<=n;j++) add(i,j);
   prim(1);
   for(int i=1;i<=m;i++)
     if(bounce[i]*bounce[i]>=ma)ans++;
     cout<<ans;



  return 0;
}
posted @ 2020-01-22 14:54  谨川  阅读(126)  评论(0编辑  收藏  举报