题目链接
https://cn.vjudge.net/contest/242377#problem/N
题目大意
给n个村落之前修路, 只要任意两个村落能互相抵达就可以, 求花费最小的方案
题目分析
题目给出给的数据并不是平常所熟悉的kruskal所含的数据 ,需要转化成 struct node{ int from,to ;double cost}e[max]; 样的数据, 其中from 表示一条边的起点, to表示这条边的终点, cost表示这条边所带的权值, 而题目所要求的就是使权值之和达到最小.
参考代码
#include<iostream>
#include<algorithm>
#include<functional>
#include<cstdio>
#include<cmath>
#include<cstring>
#define mod (int)1e9+7
#define esp 1e-9
using namespace std;
const int maxn = (int)5e3 + 5;
int per[maxn], n, m;
struct xy{ int x, y; }v[maxn]; //顶点
struct node{ int from, to; double cost; }e[maxn]; //边
int find(int x){ return per[x] == x ? x : per[x] = find(per[x]); } //查找根节点 带有路径压缩
bool cmp(node a, node b){ return a.cost< b.cost; } //按照cost从小到大 排列结构体边
double dis(xy a, xy b){ return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } //计算两点的距离
void init()
{
for (int i = 1; i <= n; i++) per[i] = i;
for (int i = 1; i <= n; i++)
cin >> v[i].x >> v[i].y;
m = 0;
for (int i = 1; i <n; i++) //转化成熟悉的kruskal, 即所谓的数据标准化
for (int j = i + 1; j <= n; j++)
{
double d = dis(v[i], v[j]);
if (d>=10 && d<=1000)
{
e[m].from = i;
e[m].to = j;
e[m++].cost = d;
}
}
sort(e, e + m, cmp);
}
void kruskral()
{
double res = 0.0;
for (int i = 0; i < m; i++)
{
int fa = find(e[i].from);
int fb = find(e[i].to);
if (fa != fb)
{
per[fa] = fb;
res += e[i].cost;
}
}
int num = 0;
for (int i = 1; i <= n; i++)
if (i == per[i])
num++; //统计根节点个数
if (num!=1)
cout << "oh!" << endl;
else
printf("%.1lf\n", res * 100);
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n;
init();
kruskral();
}
return 0;
}