病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。
现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。
在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。
输入格式:
输入在第一行中给出一个正整数 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;
}