最小生成树模板题,使用 kruskal 配合并差集
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int mx = 105;
//存储节点上级
int f[mx];
//存储两节点之间的距离
struct node {
int a, b;
double val;
};
//计算两个节点之间的距离
double length(double a[], double b[]) {
return sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]));
}
//排序op
bool cmp(node a, node b) {
return a.val < b.val;
}
//初始化数组,设置每个节点的上级是自己
void init() {
for (int i = 0; i < mx; i++) f[i] = i;
}
//寻找x节点的最上级
int fin(int x) {
return f[x] = x == f[x] ? x : fin(f[x]);
}
//将x节点和y节点连接起来
void merge(int x, int y) {
f[fin(x)] = fin(y);
}
//判断x节点和y节点是否已经连接
bool same(int x, int y) {
return fin(x) == fin(y);
}
int main() {
//freopen("in.txt", "r", stdin);
int T; cin >> T;
while (T--) {
int n; cin >> n;
double s[mx][2];
//输入节点坐标
for (int i = 0; i < n; i++) cin >> s[i][0] >> s[i][1];
//初始化
init();
int cnt = 0;
node len[mx * mx];
//计算每个节点与其他节点的距离
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
len[cnt].a = i;
len[cnt].b = j;
len[cnt++].val = length(s[i], s[j]);
}
}
//按照距离从小到大排序
sort(len, len + cnt, cmp);
double sum = 0;
for (int i = 0; i < cnt; i++) {
if (10 <= len[i].val && len[i].val <= 1000) {
if (!same(len[i].a, len[i].b)) {
//将符合条件的两个节点连接起来
merge(len[i].a, len[i].b);
sum += len[i].val;
n--;
}
}
}
//只有当n减成1的时候才说明所有节点都连起来了
if (n == 1) printf("%.1f\n", sum * 100);
else cout << "oh!" << endl;
}
}