题意:给你一棵树,之后让你求出这个树上每个点的距离的最大值。
思路:首先怎样求一个树上一个点到另外一个点的最远距离?其实就是一个点往父亲方向的最大值+往儿子方向的最大值,可知这些东西肯定都是单向的,因为你要么往儿子方向走你就只能往儿子方向走,不能再回去往父亲方向走,那么我们就可以设:
f[u]表示的是你往儿子方向的最大值,
g[u]表示的是你往父亲方向的最大值,
p[u]表示的是u的父亲,那么就有:
f[u] = max(f[v] + w(u,v)) // v 是 u 的儿子
g[u] = w(p[u],u) + max(g[p[u]] , w(u,v) + f[u]) // v 是 u的兄弟。
解释一下g[u]这个dp方程首先就是我们遍历u的父亲节点,最大值是怎样转移的?有两种情况1:从u的父亲哪里转移,2从u的兄弟哪里拐过来的,之后求一个最大值就好了
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10000 + 10;
vector<pair<int,int> >G[maxn];
int p[maxn] , f[maxn] , g[maxn];
void dfs1(int u,int fa)
{
p[u] = fa;
for(int i = 0 ; i < G[u].size() ; i ++)
{
int v = G[u][i].first , w = G[u][i].second;
if(v == fa) continue;
dfs1(v,u);
f[u] = max(f[v] + w , f[u]);
}
}
void dfs2(int u , int fa)
{
int t = 0;
g[u] = g[fa];
for(auto i : G[fa])
{
int v = i.first , w = i.second;
if(v == p[fa]) continue;
if(v == u) t = w;
else g[u] = max(g[u] , f[v] + w);
}
g[u] += t;
for(auto i : G[u])
{
int v = i.first;
if(v == fa) continue;
dfs2(v,u);
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(int i = 1 ; i <= n ;i ++) G[i].clear();
int v , w;
for(int u = 2 ; u <= n ; u++)
{
scanf("%d%d",&v,&w);
G[u].push_back(make_pair(v,w));
G[v].push_back(make_pair(u,w));
}
dfs1(1,0);
dfs2(1,0);
for(int i = 1 ; i <= n ; i++) printf("%d\n",max(f[i],g[i]));