警钟长鸣
查看原帖
警钟长鸣
695863
Prolystic楼主2024/3/10 11:54

用 Kruskal 的话,并查集初始化的时候一定不要忘记把 00 号点和 n+1n + 1 号点也初始化。如果不这样的话,会爆掉!

#include <bits/stdc++.h>
using namespace std;
using db = double;
const int N = 805;
int n, m, idx;
int x[N], y[N], fa[N];
struct Edge{
    int u, v; db w;
    bool operator <(Edge other){
        return w < other.w;
    }
}e[N * N];
void init(){
  	 // 如果写成 for(int i = 1; i <= n; i++) fa[i] = i; 就会错
    for(int i = 0; i <= n + 1; i++)
        fa[i] = i;
}
inline db getdis(int a, int b){
    db dx = fabs((db)x[a] - x[b]), dy = fabs((db)y[a] - y[b]);
    return sqrt(dx * dx + dy * dy); 
}
inline int find(int x){
    return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
db kruskal(){
    sort(e + 1, e + 1 + idx);
    db ans = -1;
    for(int i = 1; i <= idx; i++){
        int a = e[i].u, b = e[i].v;
        if(find(a) != find(b)){
            fa[find(a)] = find(b);
            ans = max(ans, e[i].w);
        }
        if(find(0) == find(n + 1))
            return ans;
    }
}
int main(){
    scanf("%d%d", &n, &m);
    init();
    for(int i = 1; i <= n; i++)
        scanf("%d%d", &x[i], &y[i]);
    for(int i = 1; i < n; i++)
        for(int j = i + 1; j <= n; j++)
            e[++idx] = (Edge){i, j, getdis(i, j) / 2};
    for(int i = 1; i <= n; i++){
        e[++idx] = (Edge){i, 0, x[i]};
        e[++idx] = (Edge){i, n + 1, n - x[i]};
    }

    printf("%.2lf", kruskal());
    return 0;
}
2024/3/10 11:54
加载中...