L2-2 病毒溯源 (25 分)
阿新 • • 發佈:2022-04-22
病毒容易發生變異。某種病毒可以通過突變產生若干變異的毒株,而這些變異的病毒又可能被誘發突變產生第二代變異,如此繼續不斷變化。
現給定一些病毒之間的變異關係,要求你找出其中最長的一條變異鏈。
在此假設給出的變異都是由突變引起的,不考慮複雜的基因重組變異問題 —— 即每一種病毒都是由唯一的一種病毒突變而來,並且不存在迴圈變異的情況。
輸入格式:
輸入在第一行中給出一個正整數 N(≤104),即病毒種類的總數。於是我們將所有病毒從 0 到 N−1 進行編號。
隨後 N 行,每行按以下格式描述一種病毒的變異情況:
k 變異株1 …… 變異株k
其中 k
是該病毒產生的變異毒株的種類數,後面跟著每種變異株的編號。第 i 行對應編號為 i 的病毒(0≤i<N)。題目保證病毒源頭有且僅有一個。
輸出格式:
首先輸出從源頭開始最長變異鏈的長度。
在第二行中輸出從源頭開始最長的一條變異鏈,編號間以 1 個空格分隔,行首尾不得有多餘空格。如果最長鏈不唯一,則輸出最小序列。
注:我們稱序列 { a1,⋯,an } 比序列 { b1,⋯,bn } “小”,如果存在 1≤k≤n 滿足 ai=bi 對所有 i<k 成立,且 ak<bk。
輸入樣例:
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
#include <bits/stdc++.h> using namespace std; #defineMAX 10001 vector<int> v[MAX]; //鄰接表 int t[MAX]; //標記陣列 vector<int>result; //存結果 void dfs(int index, vector<int> p) { if (p.size() > result.size()) { result.clear(); result = p; } for (int i = 0; i < v[index].size(); i++) { p.push_back(v[index][i]); dfs(v[index][i], p); p.pop_back(); } }int main() { int n; cin >> n; for (int i = 0; i < n; i++) { int k, x; cin >> k; while (k--) { cin >> x; v[i].push_back(x); t[x] = 1; } if (v[i].size()) sort(v[i].begin(), v[i].end()); } for (int i = 0; i < n; i++) { if (!t[i]) { vector<int>p; p.push_back(i); dfs(i, p); break; } } cout << result.size() << endl; for (int i = 0; i < result.size(); i++) { if (i) cout << " " << result[i]; else cout << result[i]; } return 0; }