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开始不断更新每个节点,不断迭代之后便是正解

代码

非复制版

img

可复制版

#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;
}

posted @ 2022-08-10 16:46  Sun-Wind  阅读(29)  评论(0编辑  收藏  举报