[题解]GYM 103328B Apple Tree

题意

给定一个 n 个节点的树,树上的每一个节点都有一个点权,每一条边都有一条边权。

现在你可以在树上任意选定一个起点出发,经过一些节点后返回该节点。

求此过程中的最大价值。(其中,价值为点权之和减去边权之和)

思路

树形 DP,定义 dpi 表示以 i 为起点所能得到的最大价值。

那么,根据题目不难得出状态转移方程:dpi=dpj2×wij+ai

由此,现在的难点就是如何确定起点。

因为树本身就是一个无向图,那么,对于两个点 u,v,从 uv 的价值与从 vu 的价值相同。

因此,dpi 的值与起点无关。

Code

#include <bits/stdc++.h>  
#define int long long  
#define re register  
  
using namespace std;  
  
const int N = 1e6 + 10,M = 2e6 + 10;  
int n,ans;  
int dp[N];  
int idx,arr[N],h[N],ne[M],e[M],w[M];  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
inline void add(int a,int b,int c){  
    ne[idx] = h[a];  
    e[idx] = b;  
    w[idx] = c;  
    h[a] = idx++;  
}  
  
inline void dfs(int u,int fa){  
    dp[u] = arr[u];  
    for (re int i = h[u];~i;i = ne[i]){  
        int j = e[i];  
        if (j == fa) continue;  
        dfs(j,u);  
        dp[u] = max(dp[u],dp[u] + dp[j] - 2 * w[i]);  
    }  
}  
  
signed main(){  
    memset(h,-1,sizeof(h));  
    n = read();  
    for (re int i = 1;i <= n;i++) arr[i] = read();  
    for (re int i = 1;i < n;i++){  
        int a,b,c;  
        a = read();  
        b = read();  
        c = read();  
        add(a,b,c);  
        add(b,a,c);  
    }  
    dfs(1,-1);  
    for (re int i = 1;i <= n;i++) ans = max(ans,dp[i]);  
    printf("%lld",ans);  
    return 0;  
}  

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18268790

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示