天梯赛 L2-038 病毒溯源C++

 

 

题目如上 ,求最长的一条变异链,且要求输出最小序列,我们先来分析一下样例,如下图:

该图演示了样例中病毒变异的过程,显然,最长的变异链有四个节点,有三条最长的变异链:

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值