病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。
现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。
在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。
输入格式:
输入在第一行中给出一个正整数 N(≤10^4),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。
随后 N 行,每行按以下格式描述一种病毒的变异情况:
k 变异株1 …… 变异株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
题目解析:
这里的坑点主要有两点:
1.最小子序列。
2.确定根节点。
如果不不注意这两点,这题其实就是一个简单的dfs。
代码解析:
#include <iostream>
using namespace std;
#include <vector>
const int N = 1e4 + 10;
vector<int> e[N];
int n;
vector<int> ret, tmp;
bool chick(vector<int>& tmp)
{
if (ret.size() > tmp.size()) return false;
else if (ret.size() == tmp.size())
{
for (int i = 0; i < ret.size(); i++)
if (ret[i] != tmp[i]) return ret[i] > tmp[i];
return false;
}
else return true;
}
void dfs(int u)
{
tmp.push_back(u);
if (chick(tmp))//判断是否是最优的,以及最小子序列
ret = tmp;
for (auto x : e[u])
{
dfs(x);
tmp.pop_back();
}
}
int main()
{
cin >> n;
int Sum = (n - 1) * n / 2;//直接一个等差数列求和
int sum = 0;
for (int i = 0; i < n; i++)
{
int k; cin >> k;
int vis = 0;
while (k--)
{
cin >> vis;
e[i].push_back(vis);
sum += vis;
}
}
int root = Sum - sum;//确定根节点,因为根节点是所有节点都不会指向它的,所以在sum中式不包括根节点的
dfs(root);
cout << ret.size() << endl;
for (int i = 0; i < ret.size(); i++)
{
cout << ret[i];
if (i < ret.size() - 1)
cout << " ";
}
return 0;
}