题目
L2-2 病毒溯源
病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。
现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。
在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。
输入格式:
输入在第一行中给出一个正整数 N(≤104),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。
随后 N 行,每行按以下格式描述一种病毒的变异情况:
k 变异株1 …… 变异株k
其中 k
是该病毒产生的变异毒株的种类数,后面跟着每种变异株的编号。第 i 行对应编号为 i 的病毒(0≤i<N)。题目保证病毒源头有且仅有一个。
输出格式:
首先输出从源头开始最长变异链的长度。
在第二行中输出从源头开始最长的一条变异链,编号间以 1 个空格分隔,行首尾不得有多余空格。如果最长链不唯一,则输出最小序列。
注:我们称序列 { a1,⋯,a**n } 比序列 { b1,⋯,b**n } “小”,如果存在 1≤k≤n 满足 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(); //回溯回溯回溯!
}
}
}
运行结果:
转载自:
(194条消息) L2-2 病毒溯源 (25 分)(Dfs详细解析)__努力努力再努力_的博客-CSDN博客
标签:Java,get,变异,int,L2,result,new,病毒,溯源 From: https://www.cnblogs.com/galo/p/17339968.html