美团2017秋招笔试【病毒传播】

【题目描述 题目描述 】给出一个图 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;
    }

}


 

猜你喜欢

转载自blog.csdn.net/qq_19446965/article/details/81263495