题目
第一行第一个数字N N个点
第一行第二个数字M 已链接M条路
下面N行,N个点的坐标
下面M行,链接路的两个点
找出损耗最小的生成树(已经连接的路不必再连接
输入
4 1
1 1
3 1
2 3
4 3
1 4
输出
4.00
思路
并查集。。先把所有连接好的并一起,之后sort一下顺寻,继续并查集
代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
struct dot
{
int x,y;
double dis;
void get_dis(pair<int,int> a, pair<int,int> b)
{
long long xx = abs(a.first - b.first);
long long yy = abs(a.second - b.second);
//这里要用LL避免溢出
dis = sqrt(xx*xx + yy * yy);//别忘记开方
return;
}
};
bool operator<(const dot& a, const dot& b)
{
return a.dis < b.dis;
}
int father[1200];
int find(int x)
{
if(x == father[x]) return x;
return father[x] = find(father[x]);
}
void U(int x, int y)
{
if(find(x) == find(y)) return;
father[find(y)] = find(x);
return;
}
int ask(int x, int y)
{
return find(x) == find(y);
}
int main()
{
int n,m;
cin >> n >> m;
vector<dot>v;
vector<pair<int,int>>p;
p.push_back({0,0});
for(int i = 1; i <= n; i++)
{
father[i] = i;
int x,y;
cin >> x >> y;
p.push_back({x,y});
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
v.push_back({i, j, 0.0});
v.back().get_dis(p[i], p[j]);
}
for(int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
if(!ask(a,b))
U(a,b);
}
sort(v.begin(), v.end());
double total = 0.0;
for(auto data : v)
{
if(!ask(data.x, data.y))
{
U(data.x, data.y);
total += data.dis;
}
}
printf("%.2lf",total);
}