zoukankan      html  css  js  c++  java
  • HDU 2196 Computer(求树上每个点的最长距离)

     

    题意:

    这题想了挺久的, 参考了kuangbin大神的代码:https://www.cnblogs.com/kuangbin/archive/2012/08/28/2659915.html

    给出树上边的长度, 求出每一个点的最长距离(就是求这个点到某一个叶子结点的距离, 这个距离最长)。

    分析:

    结点u的最长路径, 其实就是max( u到子树叶子的最长路径,  u到父亲的距离 + 父亲子树的最长路径).

    注意, 因为父亲子树的最长路径可能会经过u, 这样这个状态就不能用 u到父亲的距离 + 父亲子树的最长路径表示。

    所以记录每个节点的最长路和次长路。

    用两次dfs求解。

    第一次dfs求出每个点只看子树的最长距离和次长距离。(只关注结点本身)

    第二次dfs求出每个孩子结点的最长距离(答案)。(关注结点的孩子)

    松弛条件可以看代码。

    #include<stdio.h>
    #include<vector>
    #include<algorithm>
    #include<string.h>
    #include<iostream>
    using namespace std;
    
    const int maxn = 12000 + 7;
    const int inf = 1e9 + 7;
    int Max[maxn];// 最大距离
    int sMax[maxn];// 次大距离
    int Id[maxn];// 最大距离对应序号
    int sId[maxn];// 次大距离对应序号
    struct Edge {
        int v, d;
    };
    vector<Edge> G[maxn];
    int N;
    void init() {
        for(int i = 0; i < maxn; i ++) {
            G[i].clear();
        }
    }
    void dfs1(int u, int pre) {//更新u本身
        Max[u] = sMax[u] = 0;
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].v, d = G[u][i].d;
            if(v == pre)
                continue; //不经过父亲, 只搜索子树
            dfs1(v, u); //一直搜到叶子再回溯, 因为是根据孩子的Max更新自己的Max
            if(sMax[u] < Max[v] + d) { //如果u的次长距离 < 到v的距离  + v的最大距离
                //更新距离
                sMax[u] = Max[v] + d;
                sId[u] = v;
                if(sMax[u] > Max[u]) { //如果次长距离大于最长距离, 交换二者位置
                    swap(sMax[u], Max[u]);
                    swap(sId[u], Id[u]);
                }
            }
        }
    }
    int dfs2(int u, int pre) {//更新u的孩子
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].v, d = G[u][i].d;
            if(v == pre)
                continue; //同样不经过父亲
            if(v == Id[u]) { //如果v在u的最长路径上
                if(sMax[u] + d > sMax[v]) { //看看u的次长路 + d 是否> v的次长路
                    sMax[v] = sMax[u] + d;
                    sId[v] = u;
                    if(sMax[v] > Max[v]) { //如果次长距离大于最长距离, 交换二者位置
                        swap(sMax[v], Max[v]);
                        swap(sId[v], Id[v]);
                    }
                }
            } else { // v不在u的最长路径上
                if(d + Max[u] > sMax[v]) { //试着更新v
                    sMax[v] = d + Max[u];
                    sId[v] = u;
                    if(sMax[v] > Max[v]) { //如果次长距离大于最长距离, 交换二者位置
                        swap(sMax[v], Max[v]);
                        swap(sId[v], Id[v]);
                    }
                }
            }
            dfs2(v, u);
        }
    }
    int main() {
        while(cin >> N) {
            init();
            for(int i = 2 ; i <= N; i++) {
                int u, v, d;
                cin >> v >> d;
                G[i].push_back((Edge){v,d});
                G[v].push_back((Edge){i,d});
            }
            dfs1(1, -1);
    
            dfs2(1, -1);
    
            for(int i = 1; i <= N; i++) {
                cout << Max[i] << "
    ";
            }
        }
        return 0;
    }
  • 相关阅读:
    [课程设计]Scrum 1.5 多鱼点餐系统开发进度(点餐页面框架修复及继续布置)
    [课程设计]Scrum 1.4 多鱼点餐系统开发进度(点餐页面框架布置)
    [课程设计]Scrum 1.3 多鱼点餐系统开发进度(系统主界面框架&美化)
    任务完成情况
    SCRUM项目4.0
    操作系统 实验三 进程调度模拟程序
    Scrum 项目3.0
    操作系统 实验二、作业调度模拟程序 【完整版】
    Scrum 项目2.0
    0428 《构建之法》第6~7章读后感
  • 原文地址:https://www.cnblogs.com/Jadon97/p/9157572.html
Copyright © 2011-2022 走看看