zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 67 E.Tree Painting (树形dp)

    题目链接 

    题意:给你一棵无根树,每次你可以选择一个点从白点变成黑点(除第一个点外别的点都要和黑点相邻),变成黑点后可以获得一个权值(白点组成连通块的大小) 问怎么使权值最大

    思路:首先,一但根确定了,整棵树的权值就只需要模拟即可,所以思路就转换为求哪一个点为根的权值最大。

    这题需要用到一个二次扫描换根的思想,我们可以先从任意一个点去进行树形dp 并且得到从这个点开始去逐渐更新他的儿子节点

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<stack>
    #include<bitset>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<list>
    #include<deque>
    #include<map>
    #include<queue>
    #define ll long long int
    using namespace std;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
    int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
    const int inf=0x3f3f3f3f;
    const ll mod=1e9+7;
    int n;
    vector<int> G[200007];
    ll dp[200007]; //表示i节点以下的所有贡献
    ll f[200007];  //以i为根的权值
    ll nump[200007]; //儿子节点数(包含自己)
    void dfs(int u,int fa){
        nump[u]=1;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==fa) continue;
            dfs(v,u);
            nump[u]+=nump[v];
        }
    }
    void dfss(int u,int fa){
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==fa) continue;
            dfss(v,u);
            dp[u]+=dp[v];
        }
        dp[u]+=nump[u];
    }
    void change(int u,int fa){
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==fa) continue;
            f[v]=f[u]-nump[v]-dp[v]+n-nump[v]+dp[v]; //核心代码
            change(v,u);
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<n;i++){
            int u,v; cin>>u>>v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,0);  
        dfss(1,0);
        f[1]=dp[1];
        change(1,0);
        ll ans=0;
        for(int i=1;i<=n;i++){
            ans=max(ans,f[i]);
        }
        cout<<ans<<"
    ";
        return 0;
    }
  • 相关阅读:
    decltype类型指示符
    vector的使用
    参数使用
    CSPS模拟 43
    CSPS模拟 41
    CSPS模拟 42
    NOIP模拟 40
    NOIP模拟 39
    NOIP模拟 38
    NOIP模拟 37
  • 原文地址:https://www.cnblogs.com/wmj6/p/11125918.html
Copyright © 2011-2022 走看看