【题目描述 题目描述 】给出一个图 G(V,E),图上有 n个点, m条边,所有的都是无向。
最开始,也就是第 0天的时候,这 n个点 中有一v感染了病毒,之后的每一天凡是点都 会向它的邻居点传播病毒。经过了 t天之后,得到了感染病毒的点集 S。要求找出第 0天感染病毒的点 天感染病毒的点 v。
如果 v有很多不同的答案,把它们都找出来。
输入描述 :
第一行两个数 n,m,接下来有 m行,每两个数 u,v,表示点 ,表示点 u,v之间有一条无向边。接下来行两个 数 k,t,其中 k表示集合 S的大小。最后一行 k个数,集合 S中的元素。输 入图可能有自环和重边。输入保证 S中的数互不相同。
输出描述 :
输出一行,如果不存在这样的 v,输出 -1。
否则输出所有可能的 v,按照从小到大的顺序输出,数字之间用空格隔开不要在行末多余。
输入样例 :
4 3
3 2
1 2
1 4
3 2
4 2 1
输出样例
4
package MeiTuan;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
public class VirusTransmit {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
HashMap<Integer, HashSet<Integer>> map = new HashMap<>();
// 建图
for (int i = 0; i < m; i++) {
int k = sc.nextInt();
int v = sc.nextInt();
HashSet<Integer> value = map.getOrDefault(k, new HashSet<Integer>());
value.add(v);
map.put(k, value);
HashSet<Integer> key = map.getOrDefault(v, new HashSet<Integer>());
key.add(k);
map.put(v, key);
}
// 存储感染点
int k = sc.nextInt();
int t = sc.nextInt();
HashSet<Integer> virus = new HashSet<>();
for (int i = 0; i < k; i++) {
virus.add(sc.nextInt());
}
// 遍历病毒,逐个作为起点
int count = 0;
List<Integer> list = new ArrayList<>(virus);
Collections.sort(list);// 排序
for (int i : list) {
if (isInitial(i, t, map, virus)) {
if (count > 0)
System.out.print(" ");
count++;
System.out.print(i);
}
}
if (count == 0) {
System.out.println(-1);
}
}
public static boolean isInitial(int v, int t, HashMap<Integer, HashSet<Integer>> map, HashSet<Integer> virus) {
HashSet<Integer> vSet = new HashSet<>();// 存储v为起始的感染病毒
Queue<Integer> queue = new LinkedList<>();// 用于BFS
HashMap<Integer, Integer> layerSet = new HashMap<>();// 存储层数
HashSet<Integer> useSet = new HashSet<>();// 存储遍历过的病毒,以防回路
queue.add(v);
vSet.add(v);
int count = 0;// 传染次数
int layer = 0;
layerSet.put(v, 0);
boolean flag = true;// 跳出条件
boolean fbreak = false;// 跳出条件
while (!queue.isEmpty() && count <= t) {
int pre = queue.poll();// 出队
layer = layerSet.get(pre);// 读取层数
if (layer != count) {
count++;// 与层数不同,进入下一层
}
HashSet<Integer> PreSet = map.get(pre);// 获得邻接点
if (PreSet == null) {
continue;
}
useSet.add(pre);
for (int i : PreSet) {// 遍历邻接点
if (!useSet.contains(i)) {// 是否遍历过
if (virus.contains(i)) {// 是否是传染过的
vSet.add(i);
queue.add(i);
layerSet.put(i, count + 1);
} else {
if (count < t) {// 不是传染过的,且没到传染次数,直接pass,跳出
flag = false;
fbreak = true;
break;
}
}
}
}
if (fbreak) {
break;
}
}
if (flag && count == t && vSet.equals(virus)) {
return true;
}
return false;
}
}