在把根换到儿子时也要把作为中间点的情况加上当前点的贡献,包括最大值和次大值!
要开 long long!虽然答案不会爆 int,但是要防止减法溢出。
易错点在代码中标明:
#include <cstdio>
#define N 200005
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
const int inf = 2e9;
int n, id[N];
int tot, head[N], nxt[N * 2], ver[N * 2], e[N * 2];
long long ans, f[N][2], ff[N]; // 不开 long long 见祖宗
void insert (int x, int y, int z)
{
ver[++ tot] = y, e[tot] = z;
nxt[tot] = head[x], head[x] = tot;
return ;
}
void dp1 (int x, int fa)
{
f[x][1] = ff[x] = -inf;
for (int i = head[x], y; i; i = nxt[i])
{
if ((y = ver[i]) == fa) continue;
dp1 (y, x), f[x][0] += max (f[y][0], f[y][1] + e[i]);
}
for (int i = head[x], y; i; i = nxt[i])
{
if ((y = ver[i]) == fa) continue;
int now = f[x][0] + f[y][0] + e[i] - max (f[y][0], f[y][1] + e[i]);
if (now > f[x][1]) ff[x] = f[x][1], f[x][1] = now, id[x] = y;
else if (now > ff[x]) ff[x] = now;
}
return ;
}
void dp2 (int x, int fa)
{
ans = max (ans, f[x][0]);
for (int i = head[x], y; i; i = nxt[i])
{
if ((y = ver[i]) == fa) continue;
int f0 = f[x][0], f1 = f[x][1];
f[x][0] -= max (f[y][0], f[y][1] + e[i]);
if (id[x] != y) f[x][1] -= max (f[y][0], f[y][1] + e[i]);
else f[x][1] = ff[x] - max (f[y][0], f[y][1] + e[i]);
f[y][0] += max (f[x][0], f[x][1] + e[i]);
f[y][1] += max (f[x][0], f[x][1] + e[i]); // 要记得加
ff[y] += max (f[x][0], f[x][1] + e[i]); // 要记得加
int now = f[y][0] + f[x][0] + e[i] - max (f[x][0], f[x][1] + e[i]);
if (now > f[y][1]) ff[y] = f[y][1], f[y][1] = now, id[y] = x;
else if (now > ff[y]) ff[y] = now;
dp2 (y, x), f[x][0] = f0, f[x][1] = f1;
}
return ;
}
int main ()
{
scanf ("%d", &n);
for (int i = 1, x, y, z; i < n; i ++)
{
scanf ("%d%d%d", &x, &y, &z);
insert (x, y, z), insert (y, x, z);
}
dp1 (1, 0), dp2 (1, 0);
printf ("%lld", ans);
return 0;
}