• [10.27_P2] 统计损失 (简单树形DP)


    树形DP 简单题


    Description

    给定一棵树,每个节点有一个值。对于一条路径,它的值为路径上所有点的值的乘积。求出树上所有路径的值的和。
    注意:单个点也算一条路径。

    Input

    第 1 行一个数 n,表示树的节点数。
    第 2 行 n 个数,第 i 个数表示节点 i 的值。
    第 3 到 n+1 行,每行两个数 u,v,表示 u,v 之间有一条边。

    Output

    包含一个数,表示答案模 10086 的值。

    Sample Input

    5
    7 6 6 1 1
    1 2
    2 3
    2 4
    1 5

    Sample Output

    778

    Hint

    对于 100% 的数据,n <= 100000


    题解

    拿到题,我们可以很快看出,这应该是一道树形DP题。可以定义dp[i]为以节点 i 为根的子树的答案。然后从下往上更新。但是,等一等,如果直接这样更新,会有一点问题。如果这条路径不再往上走,或者只是经过节点 i ,向它的两个子树延伸,这样的数据向上传递后毫无作用,并且还会使答案错误。既然这样,我们可以在这个时候直接把这部分更新给ans,这就简单多了。

    代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    #define adde(u,v) {e[cnt] = (edge){v,head[u]};head[u] = &e[cnt++];}
    
    
    const int maxn = 1e5 + 5, mod = 10086;
    int n,cnt;
    int a[maxn];
    int dp[maxn];
    int ans = 0;
    
    struct edge {
    	int v;edge *next;
    }e[maxn << 1], *head[maxn];
    
    void dfs(int u,int fa) {
    	dp[u] = a[u];
    	ans = (ans + a[u]) % mod;
    	for(edge *k = head[u];k;k = k->next)if(k->v != fa) {
    		dfs(k->v,u);
    		ans = (ans+dp[k->v]*dp[u]) % mod;
    		dp[u] = (dp[u] + dp[k->v] * a[u]) % mod;
    	}
    }
    
    int main() {
    	scanf("%d",&n);
    	for(int i = 1;i <= n;i++) scanf("%d",a + i),a[i] %= mod;
    	for(int i = 1;i < n;i++) {
    		int u,v;
    		scanf("%d%d",&u,&v);adde(u,v);adde(v,u);
    	}
    	dfs(1,0);
    	printf("%d",ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    event.currentTarget
    architecture 20190628
    jQuery extend
    Prototype js library
    this._super()
    cdn for js library
    WAMPSERVER php
    characteristics of competent communicators
    onchange and oninput
    jQuery .ready()
  • 原文地址:https://www.cnblogs.com/ZegWe/p/6013179.html
Copyright © 2020-2023  润新知