$P2504 [HAOI2006]聪明的猴子$

\(problem\)

首先呢注意数组大小 别栽在自己的数组手里

求两点之间距离是
\(dis\ = \sqrt{(x1-x2)^2+(y1-y2)^2}\)

根据这个 来跑\(kruskal\)
不过特别注意的是 \(kruskal\) 也是要用并查集的。。
所以并查集的初始化 千万别省去(不然整个并查集的祖先都是0)

for(register int i=1;i<=n;i++) fa[i] = i ;

完整代码

#ifdef Dubug

#endif
#include <bits/stdc++.h>
using namespace std;
typedef long long LL ;
inline LL In() {
    LL res(0),f(1);
    register char c ;
    while(isspace(c=getchar())) ;
    c == '-'? f = -1 , c = getchar() : 0 ;
    while(res = (res << 1) + (res << 3) + (c & 15) , isdigit(c=getchar())) ;
    return res * f ;
}
int n , m ;
struct node {
    int u,v;
    double w;
};
const int N = 1000005;
node edge[N] ;
int fa[N] ;
int a[N][3] , b[N] ;
bool cmp (node x,node y) {
    return x.w < y.w ;
}
int cnt (0) ;
inline void Add(int u,int v,double w) {
    cnt ++ ;
    edge[cnt] = node {u,v,w};
    return ;
}
inline int find(int x) {
    return fa[x] == x ? fa[x] : fa[x] = find(fa[x]) ;
}
inline void merge(int x,int y) {
    fa[x] = fa[y];
}
inline void kruskal() {
    double ans ;
    int v (0) ;
    sort(edge+1,edge+cnt+1,cmp) ;
    for(register int i=1; i<=cnt; i++) {
        int x = find(edge[i].u) , y = find(edge[i].v) ;
        if(x == y) continue ;
        merge(x,y) ;
        ans = edge[i].w ;
        if(++ v == n - 1) break ;
    }
    int count = 0 ;
    for(register int i=1; i<=m; i++) ans<=b[i]?count ++:0 ;
    cout << count << endl ;
    return ;
}
signed main() {
    
    m = In() ;
    for(register int i=1; i<=m; i++) b[i] = In() ;
    n = In() ;
    for(register int i=1; i<=n; i++) a[i][1] = In() , a[i][2] = In() ;
    for(register int i=1; i<=n; i++)
        for(register int j=1; j<=n ; j++)
            if(i!=j) Add(i,j,sqrt((a[i][1]-a[j][1])*(a[i][1]-a[j][1])+(a[i][2]-a[j][2])*(a[i][2]-a[j][2]))) ;
    for(register int i=1;i<=n;i++) fa[i] = i ;
    return kruskal() , 0 ;
}
posted @ 2019-03-23 20:53  Isaunoya  阅读(293)  评论(0编辑  收藏  举报
TOP