题目
题目链接
解题思路
这是一道使用BFS解决的病毒传播问题,主要思路如下:
-
问题分析:
- 给定一个无向图 \(G(V,E)\)
- 从某个起点 \(v\) 开始传播病毒
- 每天病毒会传播给相邻节点
- 给定 \(t\) 天后的感染结果
- 求所有可能的起始点 \(v\)
-
解决方案:
- 使用BFS模拟病毒传播过程
- 对每个点作为起点进行验证
- 记录每个点被感染的时间
- 比较最终结果与给定结果是否一致
-
关键点:
- 使用邻接表存储图
- BFS计算传播时间
- 注意输出格式(空格分隔,无行末空格)
代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;const int MAXN = 1005;
vector<int> graph[MAXN]; // 邻接表存储图
bool infected[MAXN]; // 最终感染状态
int infTime[MAXN]; // 感染时间
int n, m, k, t;// BFS检查从起点v开始是否能得到给定结果
bool check(int v) {fill(infTime, infTime + n + 1, 0);queue<int> q;q.push(v);infTime[v] = 1; // 初始时间为1while (!q.empty()) {int curr = q.front();q.pop();if (infTime[curr] > t) break; // 超过时间t就停止// 遍历相邻节点for (int next : graph[curr]) {if (infTime[next] == 0) { // 未访问过infTime[next] = infTime[curr] + 1;q.push(next);}}}// 验证结果for (int i = 1; i <= n; i++) {if ((infected[i] && infTime[i] == 0) || (!infected[i] && infTime[i] != 0)) {return false;}}return true;
}int main() {cin >> n >> m;// 建图for (int i = 0; i < m; i++) {int u, v;cin >> u >> v;graph[u].push_back(v);graph[v].push_back(u);}// 读取感染结果cin >> k >> t;for (int i = 0; i < k; i++) {int x;cin >> x;infected[x] = true;}// 检查每个点作为起点vector<int> result;for (int i = 1; i <= n; i++) {if (check(i)) {result.push_back(i);}}// 输出结果if (result.empty()) {cout << "-1" << endl;} else {for (int i = 0; i < result.size(); i++) {if (i > 0) cout << " ";cout << result[i];}cout << endl;}return 0;
}
import java.util.*;public class Main {static final int MAXN = 1005;static ArrayList<Integer>[] graph = new ArrayList[MAXN];static boolean[] infected = new boolean[MAXN];static int[] infTime = new int[MAXN];static int n, m, k, t;// BFS检查从起点v开始是否能得到给定结果static boolean check(int v) {Arrays.fill(infTime, 0);Queue<Integer> q = new LinkedList<>();q.offer(v);infTime[v] = 1; // 初始时间为1while (!q.isEmpty()) {int curr = q.poll();if (infTime[curr] > t) break; // 超过时间t就停止// 遍历相邻节点for (int next : graph[curr]) {if (infTime[next] == 0) { // 未访问过infTime[next] = infTime[curr] + 1;q.offer(next);}}}// 验证结果for (int i = 1; i <= n; i++) {if ((infected[i] && infTime[i] == 0) || (!infected[i] && infTime[i] != 0)) {return false;}}return true;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();// 初始化图for (int i = 0; i < MAXN; i++) {graph[i] = new ArrayList<>();}// 建图for (int i = 0; i < m; i++) {int u = sc.nextInt();int v = sc.nextInt();graph[u].add(v);graph[v].add(u);}// 读取感染结果k = sc.nextInt();t = sc.nextInt();for (int i = 0; i < k; i++) {infected[sc.nextInt()] = true;}// 检查每个点作为起点ArrayList<Integer> result = new ArrayList<>();for (int i = 1; i <= n; i++) {if (check(i)) {result.add(i);}}// 输出结果if (result.isEmpty()) {System.out.println("-1");} else {for (int i = 0; i < result.size(); i++) {if (i > 0) System.out.print(" ");System.out.print(result.get(i));}System.out.println();}}
}
from collections import defaultdict, deque
from typing import List, Setdef check(v: int, graph: defaultdict, infected: Set[int], n: int, t: int) -> bool:"""BFS检查从起点v开始是否能得到给定结果"""inf_time = [0] * (n + 1)q = deque([v])inf_time[v] = 1 # 初始时间为1while q:curr = q.popleft()if inf_time[curr] > t: # 超过时间t就停止break# 遍历相邻节点for next_node in graph[curr]:if inf_time[next_node] == 0: # 未访问过inf_time[next_node] = inf_time[curr] + 1q.append(next_node)# 验证结果for i in range(1, n + 1):if (i in infected and inf_time[i] == 0) or \(i not in infected and inf_time[i] != 0):return Falsereturn Truedef main():# 读取图的基本信息n, m = map(int, input().split())# 建图graph = defaultdict(list)for _ in range(m):u, v = map(int, input().split())graph[u].append(v)graph[v].append(u)# 读取感染结果k, t = map(int, input().split())infected = set(map(int, input().split()))# 检查每个点作为起点result = []for i in range(1, n + 1):if check(i, graph, infected, n, t):result.append(i)# 输出结果if not result:print("-1")else:print(" ".join(map(str, result)))if __name__ == "__main__":main()
算法及复杂度
- 算法:BFS(广度优先搜索)
- 时间复杂度:\(\mathcal{O}(n(n+m))\) - 需要对每个点进行BFS
- 空间复杂度:\(\mathcal{O}(n+m)\) - 需要存储图和访问数组