题目
Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.
思路
将已经连接上的点放进同一个并查集中,再用kruskal生成MST,判断条件由一般kruskal的edgeSelected<n-1
调整为到图连通为止。
- 能用double就不用float,否则造成精度丢失
- 放进同一个并查集的时候用
root[find(a)]=find(b)
,而不是简单的root[a]=b]
,因为不能确保已知的每条边都连两个新的独立顶点
代码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 1001
#define INF 999999999
//int cost[MAXN][MAXN];typedef struct ms
{
double x, y;
}point;typedef struct ed
{
int u, v;double w;
}edge;point cord[MAXN];
int root[MAXN] = {
0 };
vector<edge> Edges;double compDis(point a, point b)
{
double dx = a.x - b.x;double dy = a.y - b.y;return sqrt(dx * dx + dy * dy);
}bool cmp(edge a, edge b)
{
return a.w < b.w;
}int find(int x)
{
int tmp = x;while (root[tmp] != tmp){
tmp = root[tmp];}int k = x;while (k != tmp){
int j = root[k];root[k] = tmp;k = j;}return tmp;
}void join(int x, int y)
{
int rootx = find(x);int rooty = find(y);if (rootx != rooty){
root[rootx] = rooty;}
}bool isConnect(int root[], int n)
{
int cnt = 0;for (int i = 1; i <= n; i++){
if (root[i] == i){
cnt++;}}if (cnt != 1) return false;return true;
}int main()
{
int n, m; cin >> n >> m;for (int i = 1; i <= n; i++){
double x, y; cin >> x >> y;cord[i] = point{
x,y };}for (int i = 1; i <= n; i++){
root[i] = i;}for (int i = 0; i < m; i++){
int a, b; cin >> a >> b;join(find(a), find(b));}for (int i = 1; i < n; i++){
for (int j = i + 1; j <= n; j++){
double w = compDis(cord[i], cord[j]);Edges.push_back(edge{
i,j,w });}}sort(Edges.begin(), Edges.end(), cmp);int i = 0;double res = 0;while (!isConnect(root,n)){
if (find(Edges[i].u) != find(Edges[i].v)){
// cout << Edges[i].u << ' ' << Edges[i].v << ' ' << Edges[i].w << endl;join(find(Edges[i].u), find(Edges[i].v));res += Edges[i].w;}i++;}cout.setf(ios::fixed);cout << setprecision(2) << res << endl;return 0;
}