• 树的直径&&树形dp


    http://acm.hdu.edu.cn/status.php
    题意:给出一棵树,求出所有结点所能到达的最远距离。
    解法一:任意一点所能到达的最远距离一定是树的直径的某一端点;由树的直径的性质可得。

    #include<bits/stdc++.h>
    
    using namespace std ;
    typedef long long ll ;
    const int N = 10010 , M = 20010 ;
    int e[M] , w[M] , ne[M] , h[N] , idx ;
    int n ;
    int p , len , d[N];//d[i]表示i结点所能到达的最远距离
    
    void add(int a , int b , int c){
        e[idx] = b , w[idx] = c , ne[idx] = h[a] , h[a] = idx++;
    }
    
    void dfs(int u , int pre, int dep){
        d[u] = max(d[u] , dep);
        if(dep > len){
            len = dep ;
            p = u ;
        }
        for(int i = h[u] ; ~i  ; i = ne[i]){
            int j = e[i];
            if(j == pre) continue;
            dfs(j , u ,  dep + w[i]);
        }
    }
    void solve(){
        memset(h , -1 , sizeof(h));
        memset(d , 0 , sizeof(d));
        p = 1 , len = 0 , idx = 0 ;
        for(int i = 2 ; i <= n ; i++){
            int a , b ;
            cin >> a >> b ;
            add(i , a , b);
            add(a , i , b);
        }
        dfs(p , 0 , 0);
        len = 0 ;
        dfs(p , 0 , 0);//直径一段
        dfs(p , 0 , 0);//直径另一端
        for(int i = 1 ; i <= n ; i++){
            cout << d[i] << endl;
        }
    }
    
    int main(){
        #ifdef ONLINE_JUDGE
    	#else
    		freopen("D:\c++\in.txt", "r", stdin);
    		//freopen("D:\c++\out.txt", "w", stdout);
    	#endif
        while(cin >> n)
            solve();
    }
    

    解法二:树形dp

    #include<bits/stdc++.h>
    
    using namespace std ;
    typedef long long ll ;
    const int N = 10010 , M = 20010 ;
    int f[N][3];//f[i][0]表示以i为子树的离i最远距离,f[i][1]表示以i为子树且与最远距离所经过的儿子不同的离i最远距离,表示f[i][2]表示i的父节点去除i子树的最远距离
    int e[M] , w[M] , ne[M] , h[N] , idx ;
    int n ;
    int maxson[N];
    void add(int a , int b , int c){
        e[idx] = b , w[idx] = c , ne[idx] = h[a] , h[a] = idx++;
    }
    
    void dfs1(int u , int pre){//处理出f[i][0] , f[i][1]
        f[u][0] = f[u][1] = 0 ;
        for(int i = h[u] ; ~i  ; i = ne[i]){
            int j = e[i];
            if(j == pre) continue;
            dfs1(j , u);
            if(f[j][0] + w[i] >= f[u][0]){
                maxson[u] = j ;
                f[u][1] = f[u][0] , f[u][0] = f[j][0] + w[i] ;
            }else if(f[j][0] + w[i] > f[u][1]){
                f[u][1] = f[j][0] + w[i] ;
            }
        }
    }
    
    void dfs2(int u , int pre){//通过父节点更新儿子的f[v][2]表示v的父节点除去v子树的最远距离
        for(int i = h[u] ; ~i ; i = ne[i]){
            int j = e[i] ;
            if(j == pre) continue ;
            if(maxson[u] != j){
                f[j][2] = max(f[u][2] , f[u][0]) + w[i] ;
            }else{
                f[j][2] = max(f[u][2] , f[u][1]) + w[i] ;
            }
            dfs2(j , u);
        }
    }
    
    void solve(){
        memset(h , -1 , sizeof(h));
        idx = 0 ;
        for(int i = 2 ; i <= n ; i++){
            int a , b ;
            cin >> a >> b ;
            add(i , a , b);
            add(a , i , b);
        }
        dfs1(1 , 0);
        dfs2(1 , 0);
        for(int i = 1 ; i <= n ; i++){
            cout << max(f[i][0] , f[i][2]) << endl;
        }
    }
    
    int main(){
        #ifdef ONLINE_JUDGE
    	#else
    		freopen("D:\c++\in.txt", "r", stdin);
    		//freopen("D:\c++\out.txt", "w", stdout);
    	#endif
        while(cin >> n)
            solve();
    }
    
  • 相关阅读:
    软件构造期末复习考点总结
    设计模式
    怎么写测试策略
    FreeRTOS任务创建、启动调度器、任务切换的过程分析——基于ARM-CotexM3
    Altium Designer 创建集成封装库(.IntLib文件)的方法
    Altium Designer多通道设计的原理与应用实例
    我的编程命名风格
    计算机网络学习笔记
    基于串口通信做my_printf时遇到的坑儿
    git常用命令
  • 原文地址:https://www.cnblogs.com/nonames/p/13623293.html
Copyright © 2020-2023  润新知