0
点赞
收藏
分享

微信扫一扫

【蓝桥杯】最小生成树

郝春妮 2022-03-26 阅读 57

最小生成树

通信

【题目链接】通电 - 蓝桥云课 (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;
}
举报

相关推荐

0 条评论