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; }