L2-2 病毒溯源 (25 分) 详解!

L2-2 病毒溯源 (25 分)

      DFS+路径优化存储

题目

在这里插入图片描述

代码

#include "bits/stdc++.h"

using namespace std;
const int G = 10000;
vector<int> Map[G]; //用一个二维动态数组来存图 (邻接表)
vector<int> res; //用来存放最终答案路径
//判断是否要优化res
bool check(vector<int> &v){
    if(v.size() < res.size()) return true; //v容器的长度比res短,证明v容器的路径比res的路径更优
    else if(v.size() == res.size()){
        for(int i=0;i<v.size();i++){ //满足题目中 如果最长链不唯一,则输出最小序列 的要求
            if(v[i]!=res[i] && v[i]<res[i]) return true; 
            if(v[i]!=res[i] && v[i]>res[i]) return false;
        }
        return false;
    } else return false;
}
//now 是当前节点 v 是当前路径
void dfs(int now,vector<int> &v){ 
    for (int i = 0; i < Map[now].size(); ++i) {
        v.push_back(Map[now][i]);
        if(check(v)) res = v; //贪心思想,边存边优化
        dfs(Map[now][i],v);
        v.pop_back();
    }
}
int main(){
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int root;
    int N;
    cin>>N;
    int sum = 0;
    int Sum = (0+N-1)*N/2; //编号可以看成一个首项为0,末项为n-1,公差为1的等差数列,这里简单求个和,用来找根节点(病毒源头)
    for (int i = 0; i < N; ++i) {
        int n;
        cin>>n;
        while (n--){
            int a;
            cin>>a; //这里出现的病毒一定是变异病毒
            Map[i].push_back(a); //存个图
            sum+=a; //将所有变异病毒的编号加起来
        }
    }
    root = Sum-sum; //简单求个根节点,好吧。
    vector<int>v; 
    //把根节点存起来
    v.push_back(root); 
    res.push_back(root);
    dfs(root,v); //暴力搜就完了,优化个屁!
    cout<<res.size()<<endl;
    for (int i = 0; i < res.size(); ++i) {
        if(i) cout<<" ";
        cout<<res[i];
    }
    return 0;
}

题解

本题难点:
      
  1.判断根节点位置;
  2.路径存储;
  3.优化存储的路径
      
解决方法
      
1.由于本题说 题目保证病毒源头有且仅有一个。 所以,所有变异的病毒统统都不是根节点,所以将所有病毒的编号加起来 int Sum = (0+N-1)*N/2; 减去变异病毒的编号就是病毒源头的编号 root
      
2. 对于路径的存储,我们可以在dfs的时候传入一个容器 V 用来存储当前的路径 dfs(int now, vectoe<int>&v); //注意这里要传入容器的引用,由于dfs属于递归函数会调用多次dfs函数,这里若是不传引用的话,系统内部会复制出来很多容器V,最终会报内存超限的错误,而传引用,每次只对当前的容器V进行操作,减少内存的使用
      
3.优化存储路径,我们可以定义一个保存最终最优解的容器 res ,对于对这个容器维护的问题,在每一次更新我们的容器 V 的时候,就可以判断 res 是否可以进行优化,其判断函数如下

bool check(vector<int>& v){
    if(v.size() < res.size()) return true; //v容器的长度比res短,证明v容器的路径比res的路径更优
    else if(v.size() == res.size()){
        for(int i=0;i<v.size();i++){ //满足题目中 如果最长链不唯一,则输出最小序列 的要求
            if(v[i]!=res[i] && v[i]<res[i]) return true; 
            if(v[i]!=res[i] && v[i]>res[i]) return false;
        }
        return false;
    } else return false;
}

V 中的路径比 res 中的路径更优时,则将 res 更新成 V 的当前路径if(check(v)) res = v;

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值