ABC222 F - Expensive Expense(树形dp换根)

Posted live4m

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ABC222 F - Expensive Expense(树形dp换根)相关的知识,希望对你有一定的参考价值。

题意:


解法:

第一次树形dp求每个点向下的max.
第二次树形dp求每个点向上的max.

第二次树形dp的时候,
对于x->v,
v向上的max等于以下两者取max:1.x向上的max,2.x向下除了v的max.
如果x向下的max是v方向的,那么情况2只能取x向下的次大值.
如果x向下的max不是v方向的,那么情况2取x向下的最大值即可.
因此x向下需要同时维护了一个最大值次大值.

其他地方就是换根的基本套路了.

code:

#include<bits/stdc++.h>
// #define MULTI_CASE
#define SYNC_OFF
#define PI pair<int,int>
#define ll long long
#define int long long
using namespace std;
// const int mod=998244353;
const int mod=1e9+7;
const int maxm=2e6+5;
vector<PI>g[maxm];
PI d[maxm][2];
int f[maxm];
int a[maxm];
int b[maxm];
int c[maxm];
int n;
void dfs1(int x,int fa){
    for(auto i:g[x]){
        int v=i.first;
        if(v==fa)continue;
        dfs1(v,x);
        //v作为重点的代价为a[v]+i.second
        //v不作为终点的代价为d[v][0].first+i.second
        //因此v方向上的最优解为两者取max
        int val=max(a[v],d[v][0].first)+i.second;
        if(val>=d[x][0].first){
            d[x][1]=d[x][0];
            d[x][0]={val,v};
        }else if(val>=d[x][1].first){
            d[x][1]={val,v};
        }
    }
}
void dfs2(int x,int fa){
    for(auto i:g[x]){
        int v=i.first;
        if(v==fa)continue;
        //x不作为终点的代价为max(f[x],d[x][0].first)+i.second
        //x作为终点的代价为a[x]+i.second
        //因此v向上的最优解为两者取max
        if(d[x][0].second!=v){
            f[v]=max(a[x],max(f[x],d[x][0].first))+i.second;
        }else{
            f[v]=max(a[x],max(f[x],d[x][1].first))+i.second;
        }
        dfs2(v,x);
    }
}
void solve(){
    cin>>n;
    for(int i=1;i<n;i++){
        int x,y,z;cin>>x>>y>>z;
        g[x].push_back({y,z});
        g[y].push_back({x,z});
    }
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    dfs1(1,1);
    dfs2(1,1);
    for(int i=1;i<=n;i++){
        int ans=max(f[i],d[i][0].first);
        cout<<ans<<endl;
    }
}
void Main(){
    #ifdef MULTI_CASE
    int T;cin>>T;while(T--)
    #endif
    solve();
}
void Init(){
    #ifdef SYNC_OFF
    ios::sync_with_stdio(0);cin.tie(0);
    #endif
    #ifndef ONLINE_JUDGE
    freopen("../in.txt","r",stdin);
    freopen("../out.txt","w",stdout);
    #endif
}
signed main(){
    Init();
    Main();
    return 0;
}

以上是关于ABC222 F - Expensive Expense(树形dp换根)的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 222 F - Expensive Expense(换根dp)

AtCoder Beginner Contest 222 F - Expensive Expense(换根dp)

ABC222 G - 222(数论,欧拉定理)

ABC222 D - Between Two Arrays(dp,差分优化)

ABC222 E - Red and Blue Tree(思维+dp)

PIC10F200/202/204/206/220/222/320/322芯片解密程序复制多少钱?