题目如上 ,求最长的一条变异链,且要求输出最小序列,我们先来分析一下样例,如下图:
该图演示了样例中病毒变异的过程,显然,最长的变异链有四个节点,有三条最长的变异链:
0 6 7 2
0 4 9 3
0 4 9 1
根据题目对最小序列的定义,显然,0 4 9 1 是这道题的答案
找到最长变异链并不难,只需要dfs一直往下暴搜就可以,关键是找最小序列需要绕个弯子
我们可以用一个vector<int> a[]来存储每个节点变异可到达的节点,即用该数组存储每条边,
注意:从小到大存储,方便我们找最小序列
详情见代码,有详细注释!!!
C++代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10010;
int b[N],c[N];
//maxx数组存储最终的最小的最长序列,cnt临时存储当前变异链
vector<int> a[N],maxx,cnt;
int n;
void dfs(int i){
//如果当前变异链的长度大于之前存储的最长链,则更新最长链
//如果相等的话,就不用管,因为我们就是从小到大枚举的,最终的maxx数组一定是最小序列
if(maxx.size()<cnt.size())maxx=cnt;
for(int j=0;j<a[i].size();j++){//枚举i的每一个变异后代
cnt.push_back(a[i][j]);
dfs(a[i][j]);
cnt.pop_back();
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
for(int j=0;j<x;j++){
scanf("%d",&b[j]);
c[b[j]]=1;//标记一下b[j]是变异病毒,即它有父节点
}
sort(b,b+x);//将节点i所有能变异到达的节点从小到大排序
for(int j=0;j<x;j++)a[i].push_back(b[j]);
}
for(int i=0;i<n;i++){
if(c[i]==0){//如果编号为i的节点是源头,则对它进行暴搜
cnt.push_back(i);
dfs(i);
break;
}
}
cout<<maxx.size()<<endl;//输出最长序列的长度
for(int i=0;i<maxx.size();i++)//输出最长序列
if(i==0)cout<<maxx[i];
else cout<<" "<<maxx[i];
cout<<endl;
return 0;
}