Codeforces Round #277 (Div. 2)Valid Sets 树DP

题意:给出一棵树,并给出每个节点上的权值,求有多少个连通子块的最大值与最小值的差不超过d。

对于每个顶点建立一颗树,然后找比它价值大的   或者   价值相等且之前没有被当作顶点建立树的点,这样就避免重复了。

dp[x]表示包涵x且以x为顶点的连通子树的个数,dp[x] = ∏ (dp[son[x]] + 1)。

注意要用long long 。

#include<iostream>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long LL;
LL d;
const LL maxn = 2222;
const LL mod = 1000000007;
struct Node
{
    LL next; LL to;
}e[maxn * 2];
LL len;
LL head[maxn];
LL dp[maxn];
LL father[maxn];
LL vis[maxn];

void add(LL from, LL to)
{
    e[len].to = to;
    e[len].next = head[from];
    head[from] = len++;
}

void build(LL root, LL pre)
{
    father[root] = pre;
    for (LL i = head[root]; i != -1; i = e[i].next){
        LL cc = e[i].to;
        if (cc == pre) continue;
        build(cc, root);
    }
}
LL val[maxn];

void dfs(LL x, LL root)
{
    dp[x] = 0; LL ans = 1;
    for (LL i = head[x]; i != -1; i = e[i].next){
        LL cc = e[i].to;
        if (cc == father[x])continue;
        if (val[cc] == val[root] && vis[cc]) continue;
        if (val[cc]<val[root] || val[cc] - val[root]>d) continue;
        //  prLLf("%I64d %I64d\n",cc,val[cc]);system("pause");
        dfs(cc, root);
        ans *= dp[cc] + 1; ans %= mod;
    }
    dp[x] += ans; dp[x] %= mod;
}

int main()
{
    LL n;
    cin >> d >> n;
    len = 0;
    memset(head, -1, sizeof(head));
    memset(vis, 0, sizeof(vis));
    for (LL i = 1; i <= n; i++)
        scanf("%I64d", &val[i]);
    for (LL i = 1; i<n; i++){
        LL a; LL b;
        scanf("%I64d%I64d", &a, &b);
        add(a, b); add(b, a);
    }
    LL ans = 0;
    for (LL i = 1; i <= n; i++){
        build(i, i); dfs(i, i);
        ans += dp[i]; vis[i] = 1;
        ans %= mod;
        //  prLLf("%I64d\n",dp[i]);
    }
    cout << ans << endl;
    return 0;
}
时间: 2024-10-14 12:46:42

Codeforces Round #277 (Div. 2)Valid Sets 树DP的相关文章

Codeforces Round #277 (Div. 2) LIS of Sequence Dp

题意: 给出一个序列,问每个位置的元素,分别属于哪一类的东西.第一类 没有出现在任何的上升子序列中. 第三类 出现在所有上升子序列中 .第二类 就是剩下的了.. 求两个东西 ,  dp[i] 表示 从1到 i 最长上升子序列的长度,dp1[i]表示从i到n 最长上升子序列的长度. 设原序列最长上升子序列长度为len 1. 若dp[i]+dp1[i] - 1 != len , 他就属于第一类. 2. 若 t  = dp[i] 的 t 出现了不止一次,且不属于第一类,那他就是第二类. 剩下的就是第三

【codeforces】Codeforces Round #277 (Div. 2) 解读

门户:Codeforces Round #277 (Div. 2) 486A. Calculating Function 裸公式= = #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; LL n ; int main () { while ( ~scanf ( "%I64d" , &n )

贪心+构造 Codeforces Round #277 (Div. 2) C. Palindrome Transformation

题目传送门 1 /* 2 贪心+构造:因为是对称的,可以全都左一半考虑,过程很简单,但是能想到就很难了 3 */ 4 /************************************************ 5 Author :Running_Time 6 Created Time :2015-8-3 9:14:02 7 File Name :B.cpp 8 *************************************************/ 9 10 #include

Codeforces Round #277 (Div. 2) d

/**  * @brief Codeforces Round #277 (Div. 2) d  * @file d.cpp  * @author 面码  * @created 2014/11/17 14:53  * @edited  2014/11/17 14:53  * @type dfs dp  *   *  */ #include <cstdio> #include <vector> #define MOD 1000000007 #define MAXN 2014 using

Codeforces Round #277 (Div. 2) c

/**  * @brief Codeforces Round #277 (Div. 2) c  * @file c.c  * @author 面码  * @created 2014/11/14 13:39  * @edited  2014/11/14 13:39  * @type greedy  *  */ #include <stdio.h> #define MAXN 100010 #define MAXC 26 #define max(a, b)  ((a) > (b) ? (a) 

Codeforces Round #277 (Div. 2) a

/**  * @brief Codeforces Round #277 (Div. 2) a  * @author xiyan  * @created 2014/11/13 11:23  * @edited  2014/11/13 11:24  * @type math   *   *  */ #include <stdio.h> long long int a; int main() {     scanf("%I64d", &a);     printf(&qu

Codeforces Round #277 (Div. 2) b

/**  * @brief Codeforces Round #277 (Div. 2) b  * @author 面码  * @created 2014/11/13 14:01  * @edited  2014/11/13 14:01  * @type greedy  * @TODO less space and time cost with bitmap   *   *  */ #include <stdio.h> #define MAXN 110 //int a[MAXN][MAXN];

Nastya Hasn&#39;t Written a Legend(Codeforces Round #546 (Div. 2)E+线段树)

题目链接 传送门 题面 题意 给你一个\(a\)数组和一个\(k\)数组,进行\(q\)次操作,操作分为两种: 将\(a_i\)增加\(x\),此时如果\(a_{i+1}<a_i+k_i\),那么就将\(a_{i+1}\)变成\(a_i+k_i\),如果\(a_{i+2}<a_i+k_i\),则将\(a_{i+2}\)变成\(a_{i+1}+k_{i+1}\),以此类推. 查询\(\sum\limits_{i=l}^{r}a_i\). 思路 我们首先存下\(k\)数组的前缀和\(sum1\),

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with