• 一个FLAG #06# 二叉树两结点间的最短路径长度


    二叉树两个结点之间的最短路径长度。完整题目见参考[1]

    #include <cstdio>
    #include <cstring>
    
    #define MAXN 20
    
    int pre[MAXN]; // 存每个结点的父结点
    int floor[MAXN]; // 存每个结点所在的层数,根结点在第1层
    int d[MAXN][MAXN]; // 保存两个结点之间的最短路径长度
    
    int getTheNearestCommonFather(int a, int b); // 找最近的公共祖先结点的id 
    
    int getAns(int a, int b)
    {
        if (d[a][b]) return d[a][b];
        
        // 若未计就计算,并保存计算过程中的结果
        
        int f_id = getTheNearestCommonFather(a, b);
         
        if (!d[a][f_id]) {  
            d[a][f_id] = d[f_id][a] = floor[a] - floor[f_id];        
        }
        
        if (!d[f_id][b]) {
            d[f_id][b] = d[b][f_id] = floor[b] - floor[f_id];
        }
        
        d[a][b] = d[b][a] = d[a][f_id] + d[f_id][b];
        
        return d[a][b];       
    }
    
    int main()
    {
        int T, n, m; // T数据组数 
        // n某组数据的结点数量
        // m某组数据的查询次数    
        
        scanf("%d", &T);
        
        int left, right; // 临时存储某结点的左右子结点 
        int a, b; // 临时存储待查询的两个结点
        while (T--) { 
            scanf("%d %d", &n, &m);
            
            memset(pre, 0, sizeof(pre));        
            memset(floor, 0, sizeof(floor));
            memset(d, 0, sizeof(d));
            
            pre[1] = 1; // 根结点的祖先还是1 该初始化似乎多余 
            floor[1] = 1; // 根结点在第1层
            for (int i = 1; i <= n ; ++i) {
                scanf("%d %d", &left, &right);    
                if (left != -1) {
                    pre[left] = i;
                    floor[left] = floor[i] + 1;        
                }
                if (right != -1) {
                    pre[right] = i;    
                    floor[right] = floor[i] + 1;        
                    // 如果数据给出顺序不规则,这里的floor初始化会有逻辑错误,需要特别处理。 
                }            
            }
    
            for (int i = 0; i != m; ++i) {
                scanf("%d %d", &a, &b);
                printf("ans: %d
    ", getAns(a, b));
            }        
        } 
        return 0;
    }
    
    // 找最近的公共祖先结点的id 
    int getTheNearestCommonFather(int a, int b)
    {    
        if (a == 1 || b == 1) return 1;
        
        int d; // 保存两结点的层数差 
        // 两结点不在同一层,转化为同一层 
        if (floor[a] > floor[b]) {
            d = floor[a] - floor[b];
            while (d--) a = pre[a];
        } 
        
        if (floor[b] > floor[a]) {
            d = floor[b] - floor[a];
            while (d--) b = pre[b];
        }
        
        // 同一层的结点找最近的公共祖先结点id
        while (a != b) {
            a = pre[a];
            b = pre[b];
        } 
        
        return a;
    }

    例题6-6 小球下落 - 直接模拟最后一个小球下落

    #include <cstdio>
    #include <cstring>
    
    int main()
    {
        int D, I; // D叶子深度 I小球个数
        
        int k;
        while (scanf("%d%d", &D, &I) == 2) {
            k = 1; // 依然用 k 来标识小球的当前位置 
            for (int i = 1; i < D; ++i) {
                if (I % 2 != 0) { // 奇数球往左走 
                    k = k * 2; 
                    I = (I + 1) / 2; // 相对左树,是第几个球 
                } else { // 偶数球往右走 
                    k = k * 2 + 1; 
                    I = I / 2; 
                }            
            }
    
            printf("%d
    ", k);
        }   
         
        return 0;
    }

    参考

    [1] Problem B 二叉树(2019计算机)_算法,二叉树_Closure-CSDN博客

    [2] 并查集详解(超级简单有趣~~就学会了)_短发-CSDN博客

  • 相关阅读:
    C/C++之文件打开方式差别
    C/C++获取文件大小
    dedecms使用
    TCP/IP概念简述
    protobuf新增message报错:类型已存在
    亚马逊MWS开发套路演示
    请求MWS报错401:Access Denied
    敏捷开发
    过滤器和拦截器的区别
    防盗链
  • 原文地址:https://www.cnblogs.com/xkxf/p/12558885.html
Copyright © 2020-2023  润新知