AtCoder Beginner Contest 222 F - Expensive Expense(换根dp)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 222 F - Expensive Expense(换根dp)相关的知识,希望对你有一定的参考价值。
定义 g [ i ] g[i] g[i]表示从 i i i出发的最长链, f [ i ] f[i] f[i]表示次长链,初始令 g [ i ] = D [ i ] g[i]=D[i] g[i]=D[i]
我们先做一遍 d f s dfs dfs,可以处理出往子树内延申的链长
现在还要求的是往父亲节点延申的最长链
那么再做一遍换根 d p dp dp.
设现在遍历到对于 u u u到 v v v这条权值 w w w的边(此时 u u u已经换根完毕,也就是 f , g f,g f,g考虑了往父节点延申的路径)
先考虑若 g [ u ] ! = g [ v ] + w g[u]!=g[v]+w g[u]!=g[v]+w,说明 u u u的最长链是往父节点更新的,所以可以用 g [ u ] + w g[u]+w g[u]+w去更新节点 v v v
若 g [ u ] = = g [ v ] + w g[u]==g[v]+w g[u]==g[v]+w,说明最长链是通过边 ( u , v , w ) (u,v,w) (u,v,w)的,所以要用 f [ u ] + w f[u]+w f[u]+w去更新节点 v v v
最后特判,若 g [ u ] = = D [ u ] g[u]==D[u] g[u]==D[u],那么令 g [ u ] = f [ u ] g[u]=f[u] g[u]=f[u]
因为不能以自己为终点,输出 g g g数组就是答案
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fi first
#define se second
const int maxn = 1e6+10;
int n,D[maxn],f[maxn],g[maxn],ans;
vector<pair<int,int> >vec[maxn];
void dfs(int u,int fa)
{
f[u] = 0, g[u] = D[u];
for(auto v:vec[u] )
{
if( v.fi==fa ) continue;
dfs( v.fi,u );
int tg = g[v.fi]+v.se;
if( tg>=g[u] ) f[u] = g[u], g[u] = tg;
else if( tg>f[u] ) f[u] = tg;
}
}
void swap_root(int u,int fa)
{
for(auto v:vec[u] )
{
if( v.fi==fa ) continue;
int val = v.se;
if( g[u]==g[v.fi]+v.se ) val += f[u];//选次长链
else val += g[u];//选取最长链
if( val>=g[v.fi] ) f[v.fi] = g[v.fi], g[v.fi] = val;
else if( val>f[v.fi] ) f[v.fi] = val;
swap_root( v.fi,u );
}
if( g[u]==D[u] ) g[u] = f[u];
}
signed main()
{
cin >> n;
for(int i=1;i<n;i++)
{
int l,r,w; cin >> l >> r >> w;
vec[l].push_back( {r,w} );
vec[r].push_back( {l,w} );
}
for(int i=1;i<=n;i++) cin >> D[i];
dfs( 1,0 ); swap_root(1,0);
for(int i=1;i<=n;i++) cout << g[i] << endl;
}
以上是关于AtCoder Beginner Contest 222 F - Expensive Expense(换根dp)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解