最小生成树
通信
【题目链接】通电 - 蓝桥云课 (lanqiao.cn)
思路:最小生成树模板题
注意事项:
-
这里不是
int
, 而是都是改为double
-
double
类型不能用memset(0x3f3f3f3f)
进行初始化g[][]和dist[]
-
建图是起点和其它所有点i
【代码实现】
prim()
算法:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1010, M = N * 2;
double INF = 1e15;
double g[N][N];
double dist[N];
bool st[N];// 点到集合的最短距离
int n, m;
struct Data
{
double x, y, h;
}datas[N];
// 题目公式给错了!!!
double get_cost(int idx1, int idx2)
{
double x1 = datas[idx1].x, y1 = datas[idx1].y, h1 = datas[idx1].h;
double x2 = datas[idx2].x, y2 = datas[idx2].y, h2 = datas[idx2].h;
double x = x1 - x2, y = y1- y2, h = h1 - h2;
double cost = sqrt(x * x + y * y) + h * h;
return cost;
}
double prim()
{
memset(st, 0, sizeof st);
for (int i = 1; i <= n; i ++ ) dist[i] = INF;
dist[1] = 0;
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(dist[t] == INF) return INF;// 不连通
// 先更新权值
res += dist[t];
st[t] = true;
for(int j = 1; j <= n; j ++) dist[j] = min(dist[j], g[t][j]);
}
return res;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ )
{
double x, y, h;
cin >> x >> y >> h;
datas[i] = {x, y, h};
}
// 初始化
for (int i = 1; i <= n; i ++ )
for(int j = i + 1; j <= n; j ++)
g[i][j] = INF;
// 建图
for (int i = 1; i <= n; i ++ )
for(int j = i + 1; j <= n; j ++)
{
double w = get_cost(i, j);
// cout << w << endl;
g[i][j] = g[j][i] = min(g[i][j], w);
}
double t = prim();
// if(t == INF) puts("impossible");
// else printf("%.2lf", t);
printf("%.2lf", t);
return 0;
}