Codeforces Round #277 (Div. 2)D题

来源:互联网 发布:二维图形变换矩阵 编辑:程序博客网 时间:2024/05/17 07:54
As you know, an undirected connected graph with n nodes and n - 1 edges is called a tree. You are given an integer d and a tree consisting of n nodes. Each node i has a value ai associated with it.

We call a set S of tree nodes valid if following conditions are satisfied:

  1. S is non-empty.
  2. S is connected. In other words, if nodes u and v are in S, then all nodes lying on the simple path between u and v should also be presented in S.
  3. .

Your task is to count the number of valid sets. Since the result can be very large, you must print its remainder modulo 1000000007(109 + 7).

Input

The first line contains two space-separated integers d (0 ≤ d ≤ 2000) and n (1 ≤ n ≤ 2000).

The second line contains n space-separated positive integers a1, a2, ..., an(1 ≤ ai ≤ 2000).

Then the next n - 1 line each contain pair of integers u and v (1 ≤ u, v ≤ n) denoting that there is an edge between u and v. It is guaranteed that these edges form a tree.

Output

Print the number of valid sets modulo 1000000007.

Sample test(s)
input1
1 4
2 1 3 2
1 2
1 3
3 4
output1
8
input2
0 3
1 2 3
1 2
2 3
output2
3
input3
4 8
7 8 7 5 4 6 4 10
1 6
1 2
5 8
1 3
3 5
output3
41
题目大意:给你一棵无根树,节点带权值,给你一个d。要求满足条件的子树有多少个。条件1:子树不为空;条件:2:子树中权值最大-权值最小<=d。
题目分析:。。。见题太少,一时无从下手。正解:由于要使子树中权值最大-权值最小<=d,我们枚举每一个节点,然后以此为根节点宽搜遍历出子树,并要求此点是子树中的权值最小的点。然后只要遍历时遇到分叉点就将所有分叉的情况相乘就可以了。
PS:当遍历到节点权值和当前遍历的根节点权值相等的话会出现重复计算的子树!这里只要在以编号小的节点为根节点时加入不管这种情况,当以编号大的节点碰到这种情况就退出当前遍历,这样处理得话就能让权值相等的只计算一次~

#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int inf = (1<<31)-10;const int MOD = (1e9)+7;vector<int>tree[2010];int d,a[2010],q[2010],f[2010];void dfs(int x,int root){    int i,j;    q[x]=1;f[x]=1;    for (i=0;i<tree[x].size();i++)        if (!q[tree[x][i]]) {            if (a[root]>a[tree[x][i]]||a[tree[x][i]]>a[root]+d) continue;            if (a[root]==a[tree[x][i]]&&tree[x][i]<root) continue;///判重!            dfs(tree[x][i],root);            f[x]=((long long)f[x]*(f[tree[x][i]]+1))%MOD;///递归求当前节点的数值。        }}int main(){    int i,j,n,u,v,ans=0;    scanf("%d%d", &d, &n);    for (i=1;i<=n;i++) scanf("%d", &a[i]);    for (i=1;i<n;i++) {        scanf("%d%d", &u, &v);        tree[u].push_back(v);        tree[v].push_back(u);    }    for (i=1;i<=n;i++) {        for (j=1;j<=n;j++) {            f[j]=0;q[j]=0;        }        dfs(i,i);///以每一个节点作为最小节点(根)遍历。        ans=(ans+f[i])%MOD;    }    printf("%d\n", ans);    return 0;}


0 0