hdu 2196 树形DP

Computer

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2390    Accepted Submission(s): 1219


Problem Description
A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious about slow functioning of the net and want to know the maximum distance Si for which i-th computer needs to send signal (i.e. length of cable to the most distant computer). You need to provide this information.


Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
 
Input
Input file contains multiple test cases.In each case there is natural number N (N<=10000) in the first line, followed by (N-1) lines with descriptions of computers. i-th line contains two natural numbers - number of computer, to which i-th computer is connected and length of cable used for connection. Total length of cable does not exceed 10^9. Numbers in lines of input are separated by a space.
 
Output
For each case output N lines. i-th line must contain number Si for i-th computer (1<=i<=N).
 
Sample Input
5 1 1 2 1 3 1 1 1
 
Sample Output
3 2 3 4 4
 
Author
scnu
 
Recommend
lcy
 
目测了众神中文算法后,自己code出来了。
两次dfs:
1.第一次,求出以当前节点u为树根的子树中离u的最大、次大权值及该路径中u的前一个节点; (后序遍历)
2.第二次,因为在第一次中求出了当前点u在其子树中的两个不同路径最大权,那么以它出发的路径最大权为:

 max{子树路径最大权,父节点fa路径最大权(如果该路径前一节点 != u)/次大权(如果该路径前一节点 != u) + 当前边权}。(前序遍历)

 有向树即可,AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<map>

using namespace std;

#define LL long long
#define ULL unsigned long long
#define UINT unsigned int
#define MAX_INT 0x7fffffff
#define cint const int
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))

#define MAXN 11111
#define MAXM 22222>>1

struct edge{
    int u, v, w, nxt;
}e[MAXM];
int h[MAXN], cc, n;
int fir_max[MAXN], sec_max[MAXN];
int fir_id[MAXN], sec_id[MAXN];

void add(int u, int v, int w){
    e[cc]=(edge){u, v, w, h[u]};
    h[u]=cc++;
}

void two_dis(int u){
    fir_max[u] = sec_max[u] = 0;
    for(int i=h[u]; i!=-1; i=e[i].nxt){
        int v=e[i].v, w=e[i].w;
        two_dis(v);                                 //搞完所有子节点再搞当前点
        if(fir_max[v]+w>=fir_max[u]){               //>=  考虑到边权为0的情况
            sec_max[u]=fir_max[u];      sec_id[u]=fir_id[u];
            fir_max[u]=fir_max[v]+w;    fir_id[u]=v;
        }
        else if(fir_max[v]+w>=sec_max[u]){
            sec_max[u]=fir_max[v]+w;
            sec_id[u]=v;
        }
    }
}

void max_dis(int u){
    for(int i=h[u]; i!=-1; i=e[i].nxt){
        int v=e[i].v, w=e[i].w;
        if(fir_id[u]!=v){                           //用从父节点出发的最大权更新
            int tw = w + fir_max[u];
            if(tw>=fir_max[v]){
                sec_max[v] = fir_max[v];    sec_id[v] = fir_id[v];
                fir_max[v] = tw;    fir_id[v] = u;
            }
            else if(tw>=sec_max[v]){
                sec_max[v] = tw;    sec_id[v] = u;
            }
        }

        if(sec_id[u]!=v){                           //次大权更新
            int tw = w + sec_max[u];
            if(tw>=fir_max[v]){
                sec_max[v] = fir_max[v];    sec_id[v] = fir_id[v];
                fir_max[v] = tw;            fir_id[v] = u;
            }
            else if(tw>=sec_max[v]){
                sec_max[v] = tw;    sec_id[v] = u;
            }
        }
        max_dis(v);                                 //去搞所有子节点
    }
}

int main(){
//    freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
    while(scanf(" %d", &n)==1){
        int u, v, w;

        memset(h, -1, sizeof(h));       cc=0;
        for(v=2; v<=n; v++){
            scanf(" %d %d", &u, &w);
            add(u, v, w);
        }
        two_dis(1);
        max_dis(1);
        for(u=1; u<=n; u++)
            printf("%d
", fir_max[u]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ramanujan/p/3358281.html