题意
先输入N表示一棵有N个结点的树,然后输入N个点的点权,然后输入M条边。要求一条链,使得链上的 ∑ \sum ∑点权和- ∑ \sum ∑边权和最大,输出这个最大值。
思路
显然是树的直径?
dp[u]表示当前到u的最长链,那么
a
n
s
=
m
a
x
(
d
p
[
u
]
+
d
p
[
e
.
v
]
−
e
.
w
)
ans = max(dp[u]+dp[e.v]-e.w)
ans=max(dp[u]+dp[e.v]−e.w),
d
p
[
u
]
=
m
a
x
(
d
p
[
e
.
v
]
+
w
[
u
]
−
e
.
w
)
;
dp[u] = max(dp[e.v] + w[u] - e.w);
dp[u]=max(dp[e.v]+w[u]−e.w);
注意先更新ans,然后在更新dp[u]
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 5;
typedef long long LL;
struct Edge
{
int u, v, w;
Edge (int u, int v, int w) : u(u), v(v), w(w) {}
};
int n, w[MAXN];
LL dp[MAXN], ans;
vector<Edge> G[MAXN];
void dfs(int u, int fa)
{
dp[u] = w[u];
for (auto e : G[u])
{
if (e.v == fa) continue;
dfs(e.v, u);
ans = max(ans, dp[u] + dp[e.v] - e.w);
dp[u] = max(dp[u], dp[e.v] + w[u] - e.w);
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &w[i]);
for (int i = 0; i < n - 1; i++)
{
int u, v, c; scanf("%d%d%d", &u, &v, &c);
u--, v--;
G[u].emplace_back(u, v, c);
G[v].emplace_back(v, u, c);
}
ans = *max_element(w, w + n);
dfs(0, -1);
printf("%lld\n", ans);
return 0;
}
/*
3
1 3 3
1 2 2
1 3 2
*/