P3478 [POI2008]STA-Station (树形dp换根)

题意:

在这里插入图片描述
在这里插入图片描述

解法:

显然是树形dp换根.
令f[v]表示以v为根的子树向上的总权值,
令d[v]表示以v为根的子树向下的总权值.

第一次dfs计算出以点1为根的树的答案,此时f[1]和d[1]是确定的.
第二次dfs计算出以每个点为根的答案.

code:

#include <bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
const int maxm=2e6+5;
vector<int>g[maxm];
int dep[maxm];
int sz[maxm];
int d[maxm];
int f[maxm];
int n;
void dfs1(int x,int fa){
    
    
    d[x]=dep[x];
    sz[x]=1;
    for(int v:g[x]){
    
    
        if(v==fa)continue;
        dep[v]=dep[x]+1;
        dfs1(v,x);
        d[x]+=d[v];
        sz[x]+=sz[v];
    }
}
void dfs2(int x,int fa){
    
    
    int tot=f[x]+d[x];//以x为根时的总权值
    for(int v:g[x]){
    
    
        if(v==fa)continue;
        d[v]-=sz[v];
        f[v]=tot;
        f[v]-=d[v]+sz[v];
        f[v]+=n-sz[v];
        dfs2(v,x);
    }
}
void solve(){
    
    
    cin>>n;
    for(int i=1;i<n;i++){
    
    
        int a,b;cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs1(1,1);
    dfs2(1,1);
    int ma=-1e18;
    int ans=0;
    for(int i=1;i<=n;i++){
    
    
        int t=f[i]+d[i];
        if(t>ma){
    
    
            ma=t;
            ans=i;
        }
    }
    cout<<ans<<endl;
}
signed main(){
    
    
    ios::sync_with_stdio(0);
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/115043327