题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196
给一棵树,求树上各点到某点的距离中最长的距离。注意每个点都要求。
和普通求树的直径不一样,要求每一个点,点的数量是10000因此每一个点都跑一次dfs就会超时。因此先随便dfs一个点,找到一个点后以此点为原点再找距离它最远的点,再找一次即可找到树直径两端的点。
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath> using namespace std; typedef struct Edge {
int v, w;
int next;
}Edge;
const int maxn = ;
int n, ecnt;
int head[maxn];
Edge e[maxn*maxn];
int dp[maxn];
int ed, lp; void init() {
memset(head, -, sizeof(head));
ecnt = ;
} void adde(int u, int v, int w) {
e[ecnt].v = v;
e[ecnt].w = w;
e[ecnt].next = head[u];
head[u] = ecnt++;
} void dfs(int u, int pre, int len) {
if(len > lp) {
lp = len;
ed = u;
}
for(int i = head[u]; ~i; i=e[i].next) {
if(e[i].v == pre) continue;
dfs(e[i].v, u, len + e[i].w);
dp[e[i].v] = max(dp[e[i].v], len+e[i].w);
}
} int main() {
// freopen("in", "r", stdin);
int v, w;
while(~scanf("%d", &n)) {
init();
for(int i = ; i <= n; i++) {
scanf("%d %d", &v, &w);
adde(i, v, w);
adde(v, i, w);
}
lp = -;
memset(dp, , sizeof(dp));
dfs(, -, );
dfs(ed, -, );
dfs(ed, -, );
for(int i = ; i <= n; i++) {
printf("%d\n", dp[i]);
}
}
return ;
}