病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。
现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。
在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。
输入格式:
输入在第一行中给出一个正整数 N(≤10
4
),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。
随后 N 行,每行按以下格式描述一种病毒的变异情况:
k 变异株1 …… 变异株k
其中 k 是该病毒产生的变异毒株的种类数,后面跟着每种变异株的编号。第 i 行对应编号为 i 的病毒(0≤i<N)。题目保证病毒源头有且仅有一个。
输出格式:
首先输出从源头开始最长变异链的长度。
在第二行中输出从源头开始最长的一条变异链,编号间以 1 个空格分隔,行首尾不得有多余空格。如果最长链不唯一,则输出最小序列。
注:我们称序列 { a
1
,⋯,a
n
} 比序列 { b
1
,⋯,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
知识点:邻接表:vector<int > v[i], 对邻接表的接点进行排序sort(v[i].begin(),v[i].end())
思路:寻找最长的链即进行深度搜索dfs(i,cnt)因为要统计最长链的个数所以要有一个cnt记录个数的参数,i为当前节点。当len==0时即遍历到了当前节点的最深处与maxcnt进行比较得到maxcnt,因为当最长链个数相同时我们要最小的序列,所以在进行dfs前要对邻接表进行排序
纠正:根节点不一定是0号,因此我们需要进行标记然后进行遍历即没有被访问到的节点即为根节点
代码:
#include<bits/stdc++.h>
using namespace std;
vector<int> v[10005];
int n;
int book[10005];
int maxcnt = -1;
int a[10005];
int b[10005];
void dfs(int i,int cnt) {
int len = v[i].size();
if (len == 0) {
if (cnt > maxcnt) {
maxcnt = cnt;
for (int k = 0;k < cnt;k++) {
b[k] = a[k];
}
}
return;
}
for (int j = 0;j < len;j++) {
a[cnt] = v[i][j];
dfs(v[i][j],cnt+1);
}
}
int main() {
cin >> n;
for (int i = 0;i < n;i++) {
int k;
cin >> k;
while (k--) {
int a;
cin >> a;
book[a] = 1;
v[i].push_back(a);
}
sort(v[i].begin(), v[i].end());
}
int i = 0;
for (;i < n;i++) {
if (book[i] == 0)
break;
}
a[0] = i;
dfs(i,1);
cout << maxcnt << endl;
for (int i = 0;i < maxcnt;i++)
if (i != maxcnt - 1)
cout << b[i] << " ";
else
cout << b[i] << endl;
}