树的直径&&树形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();
}