hdu2196
大意
给定一树,求树上每个点的最长路
思路
我们可以发现每个点的最长路都和它邻近的点有关,利用树形dp解决
首先我们可以先预处理出以1为根每个结点子树中的最长路和次长路
设dp[i][0]为第i个节点的最长路,dp[i][1]为第i个节点的次长路
在利用树形dp递归时,从1开始每遍历到一个节点,
设fa为该节点的父节点,如果dp[fa][0] == dp[i][0] + (fa与i节点之间的距离)
那么说明父节点的最长路包含了i节点,这个时候更新i节点时要用父节点的次长路去更新
从1开始不断更新每个节点,不断迭代之后便是正解
代码
非复制版
可复制版
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N = 2e4 + 5;
struct node
{
int w, ne, b;
} node[N];
bool vis[N];
int cnt = 1;
int head[N];
int dp[N][2];
int res[N];
int dfs(int x)
{
if (vis[x])
return -1;
vis[x] = true;
if (dp[x][0])
return dp[x][0];
dp[x][0] = 0;
dp[x][1] = 0;
for (int i = head[x]; i != 0; i = node[i].ne)
{
int b = node[i].b;
int c = node[i].w;
int p = dfs(b);
if(p == - 1) continue;
if (dp[x][0] > p + c)
{
dp[x][1] = max(dp[x][1], p + c);
}
else
{
dp[x][1] = dp[x][0];
dp[x][0] = p + c;
}
}
vis[x] = false;
return dp[x][0];
}
void dfs1(int x,int fa,int c){
if(vis[x]) return;
vis[x] = true;
if(dp[fa][0] == dp[x][0] + c){
// int temp = dp[x][0];
if(dp[x][0] <= dp[fa][1] + c){
dp[x][1] = dp[x][0];
dp[x][0] = dp[fa][1] + c;
}
else dp[x][1] = max(dp[x][1],dp[fa][1] + c);
}
else {
// int temp = dp[x][0];
if(dp[x][0] <= dp[fa][0] + c){
dp[x][1] = dp[x][0];
dp[x][0] = dp[fa][0] + c;
}
else dp[x][1] = max(dp[x][1],dp[fa][0] + c);
}
for(int i = head[x]; i != 0; i = node[i].ne){
int b = node[i].b;
int c = node[i].w;
dfs1(b,x,c);
}
}
void add(int a, int b, int c)
{
node[cnt].b = b;
node[cnt].w = c;
node[cnt].ne = head[a];
head[a] = cnt++;
}
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(int x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while (cin >> n)
{
for(int i = 1; i <= n; i++) vis[i] = false,dp[i][0] = dp[i][1] = head[i] = 0;
for(int i = 0; i <= cnt; i++) node[i].ne = 0;
cnt = 1;
for (int i = 2; i <= n; i++)
{
int a, b;
cin >> a >> b;
add(i, a, b);
add(a, i, b);
}
dfs(1);
dfs1(1,0,0);
for(int i = 1; i <= n; i++){
cout << dp[i][0] << endl;
}
}
return 0;
}