题意:点有正权,边有负权。在这样的无根树中找到一条权重最大的链并输出权重(树上最长路径)
题解:将无根树转为有根树,我们把1当做根
dp[u]表示节点u开始,子树先得最长路径
转移方程为:dp[u] = max(dp[u], dp[to] + a[u] - edge[i].w)
对于每一个子树,找到最长和次长的的路径
ans = max(ans, mx1 + mx2 + a[u])
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6 + 5; const ll inf = 1e18; int head[maxn], tot; struct Edge { int u, v, next; ll w; }edge[maxn]; ll a[maxn]; ll dp[maxn]; void init() { memset(head, -1, sizeof(head)); tot = 1; } void add(int u, int v, ll w) { edge[++tot].u = u; edge[tot].v = v; edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot; } ll ans = -inf; void dfs(int u, int fa) { dp[u] = a[u]; ll mx1 = -inf, mx2 = -inf; for (int i = head[u]; i != -1; i = edge[i].next) { int to = edge[i].v; if (to == fa) continue; dfs(to, u); if (dp[to] - edge[i].w > mx1) { mx2 = mx1; mx1 = dp[to] - edge[i].w; } else if (dp[to] - edge[i].w > mx2) { mx2 = dp[to] - edge[i].w; } dp[u] = max(dp[u], dp[to] - edge[i].w + a[u]); } ans = max(ans, dp[u]); ans = max(ans, mx1 + mx2 + a[u]); } int main() { int n, u, v; ll w; init(); scanf("%d", &n); for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n - 1; i++) { scanf("%d%d%lld", &u, &v, &w); add(u, v, w); add(v, u, w); } dfs(1, 0); printf("%lld\n", ans); return 0; }