zoukankan      html  css  js  c++  java
  • E. Alternating Tree 题解(树形dp)

    题目链接

    题目思路

    比较经典的求贡献问题

    求出每个点子树内和子树外和他相距奇数和偶数的点

    子数外的有点小细节

    然后分类讨论讨论求贡献

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n;
    vector<int> g[maxn];
    ll dp1[maxn][2],dp2[maxn][2];
    ll sz[maxn];
    ll a[maxn];
    ll ans=0;
    void dfs1(int son,int fa){
        sz[son]=1;
        dp1[son][0]=1;//包括自己
        for(int i=0;i<g[son].size();i++){
            int x=g[son][i];
            if(x==fa) continue;
            dfs1(x,son);
            sz[son]+=sz[x];
            dp1[son][0]+=dp1[x][1];
            dp1[son][1]+=dp1[x][0];
        }
    }
    void dfs2(int son,int fa){
        for(int i=0;i<g[son].size();i++){
            int x=g[son][i];
            if(x==fa) continue;
            dp2[x][0]=dp2[son][1]+(dp1[son][1]-dp1[x][0]);
            dp2[x][1]=dp2[son][0]+(dp1[son][0]-dp1[x][1]);
            dfs2(x,son);
        }
    }
    void dfs3(int son,int fa){
        ans+=a[son]*sz[son];
        ans=(ans%mod+mod)%mod;
        for(int i=0;i<g[son].size();i++){
            int x=g[son][i];
            if(x==fa) continue;
            ans+=a[son]*dp1[x][1]%mod*(sz[son]-sz[x]);
            ans-=a[son]*dp1[x][0]%mod*(sz[son]-sz[x]);
            ans=(ans%mod+mod)%mod;
            dfs3(x,son);
        }
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        for(int i=1,u,v;i<=n-1;i++){
            cin>>u>>v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
        dfs1(1,-1);
        dfs2(1,-1);
        dfs3(1,-1);
        // 子树外一个点 子树内一个点
        for(int i=1;i<=n;i++){
            ll add=0;
            add+=a[i]*dp1[i][0]%mod*(n-sz[i]);
            add-=a[i]*dp1[i][1]%mod*(n-sz[i]);
            add+=a[i]*dp2[i][0]%mod*sz[i];
            add-=a[i]*dp2[i][1]%mod*sz[i];
            ans=((ans+add)%mod+mod)%mod;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
    不摆烂了,写题
  • 相关阅读:
    PHP获取当前页面完整url地址,包括参数的函数
    研究在SAE上搭建最新wordpress
    CentOS6.5 编译安装lnmp环境
    cried me a river--kristinia debarge
    Bad Day -- Daniel Powter
    Back to December -- Taylor Swift
    英语单词的偏旁部首之常见前缀(一)
    21 Guns -- Green Day
    影子
    BNUOJ 1037 精神控制
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15107404.html
Copyright © 2011-2022 走看看