华为OD统一考试 - 电脑病毒感染

题目描述

一个局域网内有很多台电脑,分别标注为 0 ~ N-1 的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用 t 表示。

其中网络内一台电脑被病毒感染,求其感染网络内所有的电脑最少需要多长时间。如果最后有电脑不会感染,则返回-1。

给定一个数组 times 表示一台电脑把相邻电脑感染所用的时间。

如图:path[i] = {i, j, t} 表示:电脑 i->j,电脑 i 上的病毒感染 j,需要时间 t。

输入描述

4

3

2 1 1

2 3 1

3 4 1

2

输出描述

2

用例

输入

4

3

2 1 1

2 3 1

3 4 1

2

输出

2

说明

第一个参数:局域网内电脑个数N,1 ≤ N ≤ 200;

第二个参数:总共多少条网络连接

第三个 2 1 1 表示2->1时间为1

第六行:表示病毒最开始所在电脑号2

题目解析

用例图示如下

病毒源头是2,其中:

2->1需要时间1

2->3需要时间1,3->4需要时间1

因此最少需要时间2才能感染所有电脑。

另外,本题题目描述和用例不符。因为题目说:

一个局域网内有很多台电脑,分别标注为 0 ~ N-1 的数字。

但是题目用例,第一行给出N=4,但是第五行出现了电脑编号也是4的情况。

这影响到了下面代码中dist、visited数组长度的定义。当前代码实现以用例数据为准,即认为电脑编号是 1~N。

具体考试时需要随机应变。


import Foundation

func ODTest_2_49() {
    print("输入描述")
    print("第一个参数:局域网内电脑个数N,1 ≤ N ≤ 200;")
    let n = Int(readLine() ?? "") ?? 0
    print("第二个参数:总共多少条网络连接")
    let m = Int(readLine() ?? "") ?? 0
    print("第三个 2 1 1 表示2->1时间为1")
    var graph: [Int: [[Int]]] = [:]
    for _ in 0 ..< m {
        let data = (readLine() ?? "").split(separator: " ").map { Int($0) ?? 0 }
        let u = data[0] // 出发点
        let v = data[1] // 目标点
        let w = data[2] // 出发点到达目标点的耗时
        var list = graph[u] ?? []
        list.append([v, w])
        graph[u] = list
    }
    var dist: [Int] = Array(repeating: Int.max, count: n + 1)
    print("第六行:表示病毒最开始所在电脑号2")
    let src = Int(readLine() ?? "") ?? 0
    // 源点到达源点的耗时为0
    dist[src] = 0

    // 优先队列needCheck中记录的其实是:已被探索过的路径的终点(路径指的是源点->终点)
    // 优先队列优先级规则是,路径终点的权重(即源点->终点的耗时)越小越优先
    var needCheck: [Int] = []
    // 初始被探索过的路径只有源点本身
    needCheck.append(src)

    // 记录对应点是否在needCheck中
    var visited = Array(repeating: false, count: n + 1)
    visited[src] = true

    while !needCheck.isEmpty {
        // 取出最优路径的终点(耗时最少的路径)作为新的起点
        let cur = needCheck.removeFirst()
        visited[cur] = false
        // 如果cur有可达的其他点
        if graph.contains(where: { $0.key == cur }) {
            for next in graph[cur] ?? [] {
                // v是可达的其他店
                // w是cur->v的耗时
                let v = next[0], w = next[1]
                // 那么如果从源点到cur点的耗时是dist[cur],那么源点到v点的耗时就是dist[cur] + w
                let newDist = dist[cur] + w
                // 而源点到v的耗时之前是dist[v],因此如果newDist < dist[v],则找到更少耗时的路径
                if dist[v] > newDist {
                    // 更新源点到v的路径,即更新v点权重
                    dist[v] = newDist
                    // 如果v点不在needCheck中,则加入,因为v作为终点的路径需要加入到下一次最优路径的评比中
                    if !visited[v] {
                        visited[v] = true
                        needCheck.append(v)
                    }
                }
            }
        }
        needCheck.sort()
    }

    // dist记录的是源点到达其他各点的最短耗时,我们取出其中最大的就是源点走完所有点的最短耗时
    var ans = 0
    for i in 1 ... n {
        ans = max(ans, dist[i])
    }

    print("输出描述")
    // 如果存在某个点无法到达,则源点到该点的耗时为Integer.MAX_VALUE
    print("\(ans == Int.max ? -1 : ans)")
}

2024华为OD机试卷题 文章被收录于专栏

本专栏给大家提供了华为2024最新华为OD 题目汇总。华为OD机试刷题记录机考算法题库,帮助你上岸华为。提供C++/Java、JavaScript、Python四种语言的解法。

全部评论

相关推荐

1 1 评论
分享
牛客网
牛客企业服务