题目描述
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.
Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1..N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M ≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.
给定 nnn 个点的坐标,第 iii 个点的坐标为 (xi,yi),这 n 个点编号为 1 到 n。给定 m 条边,第 i 条边连接第 ui 个点和第 vi 个点。现在要求你添加一些边,并且能使得任意一点都可以连通其他所有点。求添加的边的总长度的最小值。
输入格式
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Two space-separated integers: Xi and Yi
* Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.
第一行两个整数 n,m 代表点数与边数。
接下来 n 行每行两个整数 xi,yi 代表第 i 个点的坐标。
接下来 m 行每行两个整数 ui,vi 代表第 iii 条边连接第 ui 个点和第 vi 个点。输出格式
* Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.
一行一个实数代表添加的边的最小长度,要求保留两位小数,为了避免误差, 请用 64 位实型变量进行计算。
输入输出样例
输入 #1
4 1 1 1 3 1 2 3 4 3 1 4输出 #1
4.00说明/提示
数据规模与约定
说明
Translated by 一只书虫仔。
思路:
将已连的边 的边权设置成 0
再将未连接的所有点 之间的边连接起来(需要计算边权)
最后跑最小生成树,把其边权相加 就是答案!
ps:这个题卡map,判断是否已连接的时候换成bool 数组来判断,用map会T两个测试点
AC代码如下:
#include <bits/stdc++.h>
#define buff \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0)
using namespace std;
const int N = 1e3 + 9;
int n, m;
struct point
{
double x, y;
} s[N];
double g[N][N];
bool st[N];
double dist[N];
//map<pair<int,int>,int> mp;//map的查找速度是log(n)级别
//.......卡map
bool mp[N][N];
void add(int a, int b, bool flag)
{
if (flag)
{
g[a][b] = 0;
g[b][a] = 0;
return ;
}
double d = sqrt((s[a].x - s[b].x) * (s[a].x - s[b].x) + (s[a].y - s[b].y) * (s[a].y - s[b].y));
g[a][b] = d;
g[b][a] = d;
}
void init()
{
for(int i = 1;i<=n;i++)
{
dist[i] = 0x3f3f3f3f;
}
}
double prim()
{
init();
double res = 0;
for (int i = 0; i < n; i++)
{
int t = -1;
for (int j = 1; j <= n; j++)
{
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
}
if (i && dist[t] == 0x3f3f3f3f)
return 0x3f3f3f3f;
if (i)
res += dist[t];
st[t] = 1;
for (int j = 1; j <= n; j++)
{
dist[j] = min(dist[j], g[t][j]);
}
}
return res;
}
int main()
{
buff;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> s[i].x >> s[i].y;
}
for (int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
add(a, b, 1);
// mp[{a,b}] = 1;
// mp[{b,a}] = 1;
mp[a][b] = 1;
mp[b][a] = 1;
}
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++)
{
if(!mp[i][j]&&i!=j)
add(i,j,0);
}
double ans = prim();
printf("%.2lf\n", ans);
}