Live2D

L2-2 病毒溯源-Java

题目

L2-2 病毒溯源

V.JPG

病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。

现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。

在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。

输入格式:

输入在第一行中给出一个正整数 N(≤104),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。

随后 N 行,每行按以下格式描述一种病毒的变异情况:

k 变异株1 …… 变异株k

其中 k 是该病毒产生的变异毒株的种类数,后面跟着每种变异株的编号。第 i 行对应编号为 i 的病毒(0≤i<N)。题目保证病毒源头有且仅有一个。

输出格式:

首先输出从源头开始最长变异链的长度。

在第二行中输出从源头开始最长的一条变异链,编号间以 1 个空格分隔,行首尾不得有多余空格。如果最长链不唯一,则输出最小序列。

注:我们称序列 { a1,⋯,a**n } 比序列 { b1,⋯,b**n } “小”,如果存在 1≤kn 满足 a**i=b**i 对所有 i<k 成立,且 a**k<b**k

输入样例:

10
3 6 4 8
0
0
0
2 5 9
0
1 7
1 2
0
2 3 1

输出样例:

4
0 4 9 1

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

题解

在这里插入图片描述

思路:

  • 用邻接表来存储变异关系
  • 需要注意的是,由于题目中要找的是最小编号的数组,所以在每次插入孩子节点的时候,需要排一个序,将大孩子放右边,小孩子放左边,这样只需要第一次找到最深的就是最短的路径

代码实现:

import java.io.*;
import java.util.*;

public class Main {
    static StreamTokenizer sc = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    //快写
    static PrintWriter out = new PrintWriter(System.out);

    //快读
    static int ini() throws IOException {
        sc.nextToken();
        return (int) sc.nval;
    }

    static LinkedList<Integer> result = new LinkedList<>();     //最终的结果
    static ArrayList<LinkedList<Integer>> edges = new ArrayList<>();    //邻接表来存储变异关系
    static LinkedList<Integer> temp = new LinkedList<>();   //临时存储(过程存储)

    public static void main(String[] args) throws IOException {
        int n = ini();
        boolean[] visited = new boolean[n];
        for (int i = 0; i < n; i++) {
            edges.add(new LinkedList<>());  //创建邻接表
        }

        for (int i = 0; i < n; i++) {
            int k = ini();
            for (int j = 0; j < k; j++) {
                int thisNum = ini();
                visited[thisNum] = true;    //对出现过的节点做标记,表明它不是根节点
                edges.get(i).add(thisNum);
            }
            Collections.sort(edges.get(i));     //每次放完孩子都需要排序,以求得最小的编号
//            System.out.println(edges.get(i));
        }

        for (int i = 0; i < n; i++) {
            if (visited[i] == false) {  //找到根节点
                temp.add(i);
                bfs(i); //从根节点开始搜索
                break;
            }
        }

        out.println(result.size());

        for (int i = 0; i < result.size(); i++) {
            if (i == 0) {
                out.print(result.get(i));
            } else {
                out.print(" " + result.get(i));
            }
        }
        out.flush();
        out.close();
    }

    private static void bfs(int index) {
        if (temp.size() > result.size()) {  //如果temp的长度>result的长度,则更新result
            result = new LinkedList<>(temp);
        }

        for (int i = 0; i < edges.get(index).size(); i++) {     //标号为index的孩子节点
            temp.add(edges.get(index).get(i));  //先将孩子节点入temp
            bfs(edges.get(index).get(i));   //对孩子节点进行深度搜索
            temp.removeLast();  //回溯回溯回溯!
        }
    }
}

运行结果:

image-20230421124731866

转载自:

(194条消息) L2-2 病毒溯源 (25 分)(Dfs详细解析)__努力努力再努力_的博客-CSDN博客

posted @   都是朕的江山  阅读(170)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
返回顶端
点击右上角即可分享
微信分享提示