We call a set S of tree nodes valid if following conditions are satisfied:
- S is non-empty.
- 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.
-
.
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).
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.
Print the number of valid sets modulo 1000000007.
#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;
}

本文介绍了一种算法,用于解决在给定一棵无根树和一个整数d的情况下,计算满足条件的子树数量的问题。条件包括子树不为空且子树中节点权值的最大值与最小值之差不超过d。

被折叠的 条评论
为什么被折叠?



