• UVA10410 树重建 Tree Reconstruction


    知识点:树的遍历

    这个题考察的是对树的dfs和bfs遍历的理解,洛谷里面有一篇题解讲的特别清楚,我就是按照那种方法做的,

    总的思路是用dfs序为基础,用bfs序为辅助来求,在dfs序上每个节点的父亲一定在这个节点的前面,那么我们就从dfs序上每个节点向前遍历找它的父亲,然后我们记录每个节点在bfs序列里面的位置,用来作为辅助,

    假设当前节点是v,我们在dfs序里面从它向前遍历,找到第一个bfs序列位置小于v在bfs序列位置的节点,设为u,那么u只可能是v的左边的兄弟或者父亲,这是至关重要的一点,这个想明白了这个题就完成了一半,因为dfs序的特性,我们开始从v向前遍历的时候,一开始就是在v的父亲的子树里面遍历的,肯定不会超出这个范围,因为上面说了是第一个,在v的父亲的子树里面,一定有bfs序位置小于v的元素,可能直接就是父亲节点,如果v有左边的兄弟节点的话,那么就是兄弟节点,这就是我的理解的方式,洛谷的题解给了另外的理解方式

    接下来,开始分类讨论判断,u在bfs序列里面的位置+1小于v在bfs序列里面的位置,也就是u和v在bfs序列里面不挨着,那么u一定是父亲,因为兄弟在bfs序列里面是一定挨着的

    else,如果u大于v,那么u是父亲,因为题目说了节点的孩子是从小到大遍历的,如果是u小于v,那么u还是可能是兄弟或者父亲,具体的说分两种情况,1,如果没有深度和u相同且权值大于u的节点,和深度和v相同且父亲权值小于u的节点,这种情况,u是v的父亲或者兄弟都满足题意,都行,自己距离画图就知道,2,除了情况1,u只能是兄弟节点,所以逻辑很清晰了,任何时候,我们把这个bfs序位置+1等于v的bfs序位置的节点,当成是兄弟都不会出错的,只有情况1的时候,它即可能是兄弟也可能是父亲,但是那样显然是得不偿失的,因为我们要判断情况1就很困难,现有的条件应该是做不到的,就算是情况1判断出来了,那么u还是可能是兄弟或者父亲,还是可以选兄弟,所以不如一开始,在当前分支下面,一律认为u是兄弟,那么兄弟的父亲是相同的,v的父亲也就找到了

    1. #include
    2. using namespace std;
    3. const int N = 1005;
    4. int main() {
    5. int n;
    6. while (cin >> n) {
    7. int a[N], b[N], bfs[N];
    8. for (int i = 1; i <= n; i++) {
    9. cin >> a[i];
    10. bfs[a[i]] = i;
    11. }
    12. for (int i = 1; i <= n; i++) {
    13. cin >> b[i];
    14. }
    15. vector<int> v[N];
    16. int fa[N];
    17. v[b[1]].push_back(b[2]);
    18. fa[b[2]] = b[1];
    19. for (int i = 3; i <= n; i++) {
    20. int j = i - 1;
    21. while (j >= 1 && bfs[b[j]] > bfs[b[i]]) j--;
    22. if (bfs[b[j]] + 1 < bfs[b[i]]) {
    23. v[b[j]].push_back(b[i]);
    24. fa[b[i]] = b[j];
    25. } else {
    26. if (b[j] > b[i]) {
    27. v[b[j]].push_back(b[i]);
    28. fa[b[i]] = b[j];
    29. } else {
    30. v[fa[b[j]]].push_back(b[i]);
    31. fa[b[i]] = fa[b[j]];
    32. }
    33. }
    34. }
    35. for (int i = 1; i <= n; i++) {
    36. cout << i << ':';
    37. for (int j = 0; j < (int) v[i].size(); j++) {
    38. cout << ' ' << v[i][j];
    39. }
    40. cout << '\n';
    41. }
    42. }
    43. return 0;
    44. }

  • 相关阅读:
    Linux系统常用命令总结-2022
    linux中yum -y install mysql为什么默认是mariadb?以及mysql yum源的配置
    代码随想录算法训练营第五十五天 | 动态规划 part 12 | 300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组
    IDEA 2023.2.2 使用 Scala 编译报错 No scalac found to compile scala sources
    ArrayList知识点(面试)
    【数据结构】图的遍历:广度优先(BFS),深度优先(DFS)
    卡尔曼滤波算法原理
    没有专业背景,还有机会成为机器学习工程师吗?
    第三站:函数(第三幕)递归训练
    Dockerfile架设LNMP
  • 原文地址:https://blog.csdn.net/m0_73035684/article/details/128076131