华为机考真题 -- 5G网络建设

题目描述:

现需要在某城市进行 5G 网络建设,已经选取 N 个地点设置 5G 基站,编号固定为 1 到 N,接下来需要各个基站之间使用光纤进行连接以确保基站能互联互通,不同基站之间架设光纤的成本各不相同,且有些节点之间已经存在光纤相连,请你设计算法,计算出能联通这些基站的最小成本是多少。

注意:基站的联通具有传递性,基站 A 与基站 B之间 架设了光纤,基站 B 与基站 C 也架设了光纤,则基站 A 与基站 C 视为可以互相联通

输入描述:

第一行输入表示基站的个数 N,其中 0<N<=20;
第二行输入表示具备光纤直连条件的基站对的数目 M,其中 0<M<N*(N-1)/2;
从第三行开始连续输入 M 行数据,格式为 X Y Z P,其中 X Y 表示基站的编号,0<X<=N,0<Y<=N 且 x 不等于 y,Z 表示在 X Y 之间架设光纤的成本,其中 0<Z<100,P 表示是否已存在光纤连接,0 表示未连接,1 表示已连接

输出描述:

如果给定条件,可以建设成功互联互通的 5G 网络,则输出最小的建设成本;
如果给定条件,无法建设成功互联互通的 5G 网络,则输出-1;

示例 1:

输入
3
3
1 2 3 0
1 3 1 0
2 3 5 0

输出
4

说明:只需要在 1,2 以及 2,3 基站之间铺设光纤,其成本为 3+1=4

示例 2:

输入
3
1
1 2 5 0

输出
-1
说明:3 基站无法与其他基站连接,输出-1

示例 3:

输入
3
3
1 2 3 0
1 3 1 0
2 3 5 1

输出
1
说明:2,3 基站已有光纤相连,只有要再 1,3 站点之间铺设光纤,其成本为 1

C++源码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class UnionFind {
public:
    vector<int> parent;

    UnionFind(int size) {
        parent.resize(size);
        for (int i = 0; i < size; ++i) {
            parent[i] = i;
        }
    }

    int find(int p) {
        if (parent[p] != p) {
            parent[p] = find(parent[p]);  // 路径压缩
        }
        return parent[p];
    }

    bool unionSets(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP != rootQ) {
            parent[rootP] = rootQ;
            return true;
        }
        return false;
    }
};

int kruskal(int n, vector<vector<int>>& edges) {
    UnionFind uf(n);
    sort(edges.begin(), edges.end(), [](const vector<int>& a, const vector<int>& b) {
        return a[2] < b[2];  // 按成本排序
        });

    int total_cost = 0;
    int edges_used = 0;

    for (const auto& edge : edges) {
        int u = edge[0], v = edge[1], cost = edge[2];
        if (uf.unionSets(u, v)) {
            total_cost += cost;
            edges_used++;
            if (edges_used == n - 1) {
                return total_cost;
            }
        }
    }

    return (edges_used == n - 1) ? total_cost : -1;
}

int main() {
    int n, m;
    cin >> n;  // 基站个数
    cin >> m;  // 连接个数

    vector<vector<int>> edges;
    for (int i = 0; i < m; ++i) {
        int x, y, z, p;
        cin >> x >> y >> z >> p;
        x--;   // 转换为0基索引
        y--;
        if (p == 1) {
            z = 0;  // 如果已经连接,则视为成本为0
        }
        edges.push_back({ x, y, z });
    }

    // 计算最小生成树的成本
    int result = kruskal(n, edges);
    cout << result << endl;

    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值