题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196
题目:
题意:有n台电脑,每台电脑连接其他电脑,第i行(包括第一行的n)连接u,长度为w,问你每个节点能够连接的最远距离。
思路:树形dp,由于本题是一棵有根树(根节点为1),所以每个节点能到达的最远距离为max(从父亲节点往上传并到达根节点的其他子树的最远距离,从子节点到达的最远距离)。为了获得这两个信息,那么我们就需要把信息从子节点往父亲节点传和从父亲节点往子节点传,因此我们需要两个dfs,第一个处理出当前节点u从子节点能够到达的最远距离(记为dp[u][0]),次远距离(记为dp[u][1]),第二个处理从父亲节点能够到达的最远距离(记为dp[u][2]),最后每个节点能够到达的最远距离就是max(dp[u][0],dp[u][2])。我们为什么要记录dp[u][1]呢?原因是当你在第二遍dfs时,你记录dp[u][2]就得判断是dp[u][0]和dp[u][2]比较还是dp[u][1]和dp[u][2]比较(当前节点为v,v的父亲节点为u),而这个判断的依据就是u从子节点到达的最远距离是否就是通过跑v这条子链跑出来的,如果是跑这条链跑出来的,那么肯定是要用dp[u][1]来进行比较,反之就是dp[u][0]。(实在不好理解的请手动画个图辅助理解~)我们知道树的直径是树上最长链的长度,根据这题处理出来的信息我们容易知道树的直径就是max{max(dp[u][0],dp[u][2])+dp[u][0],u为1~n}。
代码实现如下:
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long ll;
typedef unsigned long long ull; #define bug printf("*********\n");
#define FIN freopen("in.txt", "r", stdin);
#define debug(x) cout<<"["<<x<<"]" <<endl;
#define IO ios::sync_with_stdio(false),cin.tie(0); const int mod = 1e9 + ;
const int maxn = 1e4 + ;
const double pi = acos(-);
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f; int n, u, v;
int dp[maxn][]; struct edge {
int v, w;
edge(int v = , int w = ) : v(v), w(w) {}
}; vector<edge> G[maxn]; void init() {
memset(dp, , sizeof(dp));
for(int i = ; i < maxn; i++) {
G[i].clear();
}
} void dfs1(int u) {
int v, w;
for(int i = ; i < G[u].size(); i++) {
v = G[u][i].v, w = G[u][i].w;
dfs1(v);
if(dp[v][] + w > dp[u][]) {
dp[u][] = max(dp[u][], dp[u][]);
dp[u][] = dp[v][] + w;
} else {
dp[u][] = max(dp[u][], dp[v][] + w);
}
}
} void dfs2(int u) {
int v, w;
for(int i = ; i < G[u].size(); i++) {
v = G[u][i].v, w = G[u][i].w;
if(dp[u][] == dp[v][] + w) {
dp[v][] = max(dp[u][], dp[u][]) + w;
} else {
dp[v][] = max(dp[u][], dp[u][]) + w;
}
dfs2(v);
}
} int main() {
//FIN;
while(~scanf("%d", &n)) {
init();
for(int i = ; i <= n; i++) {
scanf("%d%d", &u, &v);
G[u].push_back(edge(i, v));
}
dfs1();
dfs2();
for(int i = ; i <= n; i++) {
printf("%d\n", max(dp[i][], dp[i][]));
}
}
return ;
}