电脑病毒感染 - 华为OD统一考试
OD统一考试
题解: Java / Python / C++
题目描述
一个局域网只内有很多台电脑,分别标注为 1 ~ N 的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t 表示。
其中网络内一台电脑被病毒感染,求其感染网络内所有的电脑最少需要多长时间。如果最后有电脑不会感染,则返回-1。
给定一个数组 times 表示一台电脑把相邻电脑感染所用的时间: path[i] = {i, j, t} 表示: 电脑i 上的病毒感染 j,需要时间 t 。
输入描述
第一行输入一个整数N,表示局域网内电脑个数 N,1<= N<= 200 ;
第二行输入一个整数M, 表示有 M 条网络连接;
接下来M行, 每行输入为 i,j,t 。表示电脑 i 感染电脑 j 需要时间t。(1 <= i, j <= N)
最后一行为病毒所在的电脑编号。
输出描述
输出最少需要多少时间才能感染全部电脑,如果不存在输出 -1
示例1
输入:
4
3
2 1 1
2 3 1
3 4 1
2
输出:
2
示例2
输入:
4
3
2 1 1
2 3 1
3 4 1
3
输出:
-1
题解
经典的最短路径问题,使用 Dijkstra 算法求解。
代码思路:
1、 图的构建:使用 g 表示图,其中键为电脑编号,值为与该电脑相邻的电脑以及感染所需的时间。
2、优先队列:使用 heap 作为优先队列,队列中存储的是数组
{时间, 电脑编号}
。3、Dijkstra 算法:开始时,将病毒所在电脑加入队列,并设置时间为0。然后,不断从队列中取出时间最小的电脑,将其相邻的未感染电脑加入队列,并更新感染时间。重复这个过程直到所有电脑都被感染或队列为空。
4、输出结果:根据感染情况输出结果。
Java
import java.util.*;
/**
* @author code5bug
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt(), M = scanner.nextInt();
// 构建图
Map<Integer, List<int[]>> g = new HashMap<>();
for (int i = 0; i < M; ++i) {
int a = scanner.nextInt(), b = scanner.nextInt(), t = scanner.nextInt();
g.computeIfAbsent(a, k -> new ArrayList<>()).add(new int[]{b, t});
}
// 病毒所在的编号, 优先级队列,已经感染的电脑集合
int sid = scanner.nextInt();
PriorityQueue<int[]> heap = new PriorityQueue<>(Comparator.comparingInt(arr -> arr[0]));
Set<Integer> vis = new HashSet<>();
heap.add(new int[]{0, sid});
while (!heap.isEmpty()) {
int[] arr = heap.poll();
int time = arr[0], id = arr[1];
vis.add(id);
if (N == vis.size()) { // 感染了所有电脑
System.out.println(time);
return;
}
for (int[] neighbor : g.getOrDefault(id, Collections.emptyList())) {
int nextId = neighbor[0], costTime = neighbor[1];
if (!vis.contains(nextId)) { // 此时 nextId 电脑还没有被感染
heap.add(new int[]{time + costTime, nextId});
}
}
}
if (N != vis.size()) {
System.out.println(-1);
}
}
}
Python
from collections import defaultdict
from heapq import heappop, heappush
N = int(input())
M = int(input())
# 构建图
g = defaultdict(set)
for _ in range(M):
i, j, t = map(int, input().split())
g[i].add((j, t))
# 病毒所在的编号, 优先级队列,已经感染的电脑集合
sid, heap, vis = int(input()), [], set()
heappush(heap, (0, sid))
while heap:
time, id = heappop(heap)
vis.add(id)
if N == len(vis): # 感染了所有电脑
print(time)
break
for next_id, cost_time in g[id]:
if next_id not in vis: # 此时 next_id 电脑还没有被感染
heappush(heap, (time + cost_time, next_id))
if N != len(vis):
print(-1)
C++
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <unordered_set>
using namespace std;
int main() {
int N, M;
cin >> N >> M;
// 构建图
unordered_map<int, vector<pair<int, int>>> g;
for (int i = 0; i < M; ++i) {
int a, b, t;
cin >> a >> b >> t;
g[a].push_back({b, t});
}
// 病毒所在的编号, 优先级队列,已经感染的电脑集合
int sid;
cin >> sid;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> heap;
unordered_set<int> vis;
heap.push({0, sid});
while (!heap.empty()) {
auto [time, id] = heap.top();
heap.pop();
vis.insert(id);
if (N == vis.size()) { // 感染了所有电脑
cout << time << endl;
return 0;
}
for (const auto& neighbor : g[id]) {
int next_id = neighbor.first;
int cost_time = neighbor.second;
if (vis.find(next_id) == vis.end()) { // 此时 next_id 电脑还没有被感染
heap.push({time + cost_time, next_id});
}
}
}
if (N != vis.size()) {
cout << -1 << endl;
}
return 0;
}
相关练习题
题号 | 题目 | 难易 |
---|---|---|
LeetCode 743 | 743. 网络延迟时间 | 中等 |
🙏整理题解不易, 如果有帮助到您,请给点个赞 ❤️ 和收藏 ⭐,让更多的人看到。🙏🙏🙏