题目地址:畅通工程再续
①Kruskal算法:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 110;
const int MAX = 10010;
int fa[maxn];
struct Node //建立坐标
{
double x; //不用double会WA!!
double y;
}a[maxn];
struct Edge //建立权值
{
int u;
int v;
double len;
}b[MAX];
void init(int n) //初始化根节点
{
for(int i = 0; i < n; i++)
fa[i] = i;
}
int Find(int x) //寻找根节点
{
int r = x;
while(fa[r] != r) {
r = fa[r];
}
return r;
}
int cmp(Edge x, Edge y) //根据权值从小到大排序
{
return x.len < y.len;
}
bool join(int x, int y)
{
int fx = Find(x);
int fy = Find(y);
if(fx != fy) {
fa[fx] = fy;
return true;
}
else
return false;
}
int main()
{
int t, n;
cin >> t;
while(t--) {
cin >> n;
int num = 1;
double sum = 0;
init(n);
for(int i = 0; i < n; i++) {
scanf("%lf%lf", &a[i].x, &a[i].y);
}
//建图
int i , j, k;
for(i = 0, k = 0; i < n; i++) {
for(j = i+1; j < n; j++) {
b[k].u = i;
b[k].v = j;
b[k].len = sqrt(pow(a[i].x - a[j].x, 2) + pow(a[i].y - a[j].y, 2));
k++;
}
}
sort(b, b + k, cmp);
for(i = 0; i < k; i++) {
if(b[i].len >= 10 && b[i].len <= 1000) {
if(join(b[i].u, b[i].v)) {
sum += b[i].len;
num++;
}
}
}
if(num == n) {
printf("%.1lf\n", sum*100);
}
else
printf("oh!\n");
}
return 0;
}