DFS+打印路径+最小字典序

题目详情 - L2-038 病毒溯源 (25 分) (pintia.cn)

思路:
搜索策略:从根节点往下搜索,对非根节点搜索无意义,还会超时。只要对所有一个节点的所有子节点按照升序排序,那么搜索到的第一个长度最长的路径就是答案。

记录路径:使用一个记录父节点(前驱节点)的数组,这样只要记录最长路径的末尾结点即可反推回整条路径

 AC代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 100010;

vector<int> v[N], path;
int last, depth, root;
int n, pre[N];

void dfs(int val, int u)    //节点值为val,第u层
{
    if(u > depth)   //如果路径长度增长,修正尾节点和深度(长度)
    {
        depth = u;
        last = val;
    }
    for(int i = 0; i < v[val].size(); i ++ )
        dfs(v[val][i], u + 1);
}

int main()
{
    cin >> n;
    for(int i = 0; i < n; i ++ )    pre[i] = -1;
        
    for(int i = 0; i < n; i ++ )
    {
        int k;  cin >> k;
        for(int j = 0; j < k; j ++ )
        {
            int x;  cin >> x;
            pre[x] = i;
            v[i].push_back(x);
        }
        sort(v[i].begin(), v[i].end()); //对所有子节点排序
    }
    
    for(int i = 0; i < n; i ++ )
        if(pre[i] == -1)
        {
            root = i;   break;
        }
    
    dfs(root, 1);
    
    while(last != -1)   //逆推路径
    {
        path.push_back(last);
        last = pre[last];
    }
    
    cout << depth << endl;
    reverse(path.begin(), path.end());
    for(int i = 0; i < path.size(); i ++ )
    {
        cout << path[i];
        if(i != path.size() - 1)    cout << " ";
    }
    
    
    return 0;
}






posted @ 2022-05-05 08:41  光風霽月  阅读(32)  评论(0编辑  收藏  举报