【Educational Codeforces Round 67 (Rated for Div. 2)】E. Tree Painting(換根DP)

題面

題意:

一棵樹,有nn個節點,現在要找一個點作爲根節點使得這棵樹的所有子樹的大小和最大。求出最大值。

思路:

先利用一次dfs求出以1爲根的答案,順便統計一下以ii爲根節點的子樹的大小sizisiz_i和以ii爲根節點的子樹的所有子樹的大小和dpidp_i
再進行一次dfs進行換根操作更新最大值,設dpudp_u爲以uu爲根時的答案,那麼想要得到以它的孩子vv爲根的答案dpvdp_v,首先需要斷掉u,vu,v之間的邊,那麼斷掉vv後剩下的大小爲res=dpusizvdpvres=dp_u-siz_v-dp_v。然那麼dpvdp_v就等於dpv+tmpsizv+ndp_v+tmp-siz_v+n

code

#include<bits/stdc++.h>
 
using namespace std;
const long long N = 1e6+100;
vector<long long> G[N];
long long dp[N];long long siz[N];
void dfs1(long long u,long long fa){
    siz[u]=1;
    for(auto v:G[u]){
        if(v==fa) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        dp[u]+=dp[v];
    }
    dp[u]+=siz[u];
}
long long ans=0;
long long n,u,v;
void dfs2(long long u,long long fa){
    ans=max(ans,dp[u]);
    for(auto v:G[u]){
        if(v==fa) continue;
        long long res=dp[u]-dp[v]-siz[v];
        dp[v]=(dp[v]+res+n-siz[v]);
        dfs2(v,u);
    }
}
int main(){
    cin>>n;
    for(long long i=1;i<=n-1;i++){
        cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1,0);
    dfs2(1,0);
    cout<<ans<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章