电脑
题目描述:
水题,一棵树,每个节点的最远距离
题解:
树形dp,先跑出来dpm和dps,然后再dfs,参数含fa的去掉儿子的len,之后比较找出当前u的结果以及u的去掉儿子的len,传下去
重点:
标准的u去掉儿子的len以及求u的最远距离
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)
typedef long long ll;
using namespace std;
const int maxn = 1e4 +100;
struct info
{
int to, len;
};
vector<info> G[maxn];
int n, dpm[maxn], dps[maxn];
int s[maxn];
void dfs_s(int u, int fa, int fa_l, int fa_len)//fa_len是fa到u的长度.fa_l是fa的去掉儿子的长度.
{
int l = 0;
if(fa == 0)//第一次
{
l = 0;
s[u] = dpm[u];
REP(i, 0, G[u].size())
{
int v = G[u][i].to, len = G[u][i].len;
if(v!=fa)
{
dfs_s(v, u, l, len);
}
}
}
else
{
l = fa_l;
if(dpm[fa]==fa_len+dpm[u])//先搞出fa带上不是u的儿子的最长链
{
l = max(l, dps[fa]);
}
else
{
l = max(l, dpm[fa]);
}
l += fa_len;//u不带儿子的最长链
s[u] = max(dpm[u], l);//结果
REP(i, 0, G[u].size())
{
int v = G[u][i].to, len = G[u][i].len;
if(v!=fa)
{
dfs_s(v, u, l, len);
}
}
}
}
void dfs(int u, int fa)//正常的,找出dpm和dps
{
dpm[u] = dps[u] = 0;
REP(i, 0, G[u].size())
{
int v = G[u][i].to, len = G[u][i].len;
if(v!=fa)
{
dfs(v, u);
int t = dpm[v] + len;//只用每一个儿子的最长来更新就好.
if(t > dpm[u])
{
dps[u] = dpm[u];
dpm[u] = t;
}
else if(t > dps[u])
{
dps[u] = t;
}
}
}
}
void solve()
{
dfs(1, 0);
dfs_s(1, 0, 0, 0);
REP_D(i, 1, n)
{
printf("%d\n", s[i]);
}
}
int main()
{
// freopen("1Ain.txt", "r", stdin);
//freopen("1Aout.txt", "w", stdout);
while(scanf("%d", &n) != EOF)
{
REP_D(i, 1, n)
{
G[i].clear();
}
REP_D(i, 2, n)
{
int b, len;
scanf("%d%d", &b, &len);
info t;
t.to = b;
t.len = len;
G[i].push_back(t);
t.to = i;
G[b].push_back(t);
}
solve();
}
return 0;
}