L2-038 病毒溯源
v[ i ] 中保存第 i 种病毒可能产生的变异病毒编号,in[ i ] 中保存编号 i 的入度,入度为零的病毒为源头病毒,pre[ i ] 中保存病毒由哪种病毒变异而来(上级病毒)。为了保证序列最小,在输入 v[ i ]后可对其进行一次排序,然后通过 BFS 找到变异次数,过程中由 res 和 idx 标记最多变异次数量以及对应的病毒编号,最后通过pre找回完整变异链。
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e4 + 10;
int n, in[N], pre[N];
int s; // 源头
vector<int> v[N], ans;
queue<PII> q;
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++) {
int k;
scanf("%d", &k);
for (int j = 0; j < k; j++) {
int x;
scanf("%d", &x);
in[x] ++;
pre[x] = i;
v[i].push_back(x);
}
sort(v[i].begin(), v[i].end());
}
for (int i = 0; i < n; i++) if (!in[i]) s = i;
int res = 0, idx;
q.push({s, 1});
while (!q.empty()) {
auto t = q.front();
int a = t.first, b = t.second;
q.pop();
if (b > res) {
res = b;
idx = a;
}
for (auto it : v[a]) q.push({it, b + 1});
}
printf("%d\n", res);
while (idx != s) {
ans.push_back(idx);
idx = pre[idx];
}
ans.push_back(s);
for (int i = ans.size() - 1; i > 0; i--)
printf("%d ", ans[i]);
printf("%d\n", ans[0]);
return 0;
}