Valid Sets

Codeforces Round #277 (Div. 2)   D. Valid Sets

链接:http://codeforces.com/contest/486/problem/D

解题思路:1.首先,考虑没有树的节点value情况,那就简化成了求一颗树的所有子树,用dp很容易就可以得到。

      即:dp[u]=∏(dp[v]+1)    ,其中u是父节点,v是子节点。

     2.需要寻找节点value之差不超过d的子树,考虑到找到的子树一定会存在一个value最小的点,所以把每个节点做为根节点,

      形成n颗所有节点满足 a[v]>=a[root]&&a[v]<=a[root]+d的树,把每颗树的根节点的dp[root]加起来就是总数。

     3.注意中间过程的取模,同时注意出现节点value一样的情况,避免重复计算。

代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <cmath>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int maxn = 2000 + 10;
10 const int MOD = 1e9 + 7;
11 
12 vector<int> node[maxn];
13 int a[maxn];
14 long long dp[maxn];
15 bool f[maxn];
16 int d, n;
17 
18 void dfs(int u, int root)
19 {
20     for (int i = 0; i < node[u].size(); i++)
21     {
22         f[u] = 1;
23         int v = node[u][i];
24         if(f[v] == 0 && ((a[v] > a[root] && a[v] <= a[root] + d) || (a[v] == a[root] && v > root)))
25         {
26             dfs(v, root);
27             dp[u] = (dp[u] * (dp[v] + 1)) % MOD;
28         }
29     }
30 }
31 
32 int main()
33 {
34     while(scanf("%d%d", &d, &n) != EOF)
35     {
36         for (int i = 1; i <= n; i++)
37         {
38             scanf("%d", &a[i]);
39         }
40         for (int i = 0; i < n - 1; i++)
41         {
42             int u, v;
43             scanf("%d%d", &u, &v);
44             node[u].push_back(v);
45             node[v].push_back(u);
46         }
47         int sum = 0;
48         for (int i = 1; i <= n; i++)
49         {
50             memset(f, 0, sizeof(f));
51             for (int j = 1; j <= n; j++)
52             {
53                 dp[j] = 1;
54             }
55             dfs(i, i);
56             sum = (sum + dp[i]) % MOD;
57         }
58         printf("%d\n", sum);
59     }    
60     
61     
62 
63     return 0;
64 }

AC如下:

posted @ 2014-11-22 15:40  sunjieee  阅读(199)  评论(0编辑  收藏  举报