码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 486D

时间:2019-02-28 01:03:14      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:can   计数   ret   show   pen   event   个数   原来   lap   

题意:

给一棵树,每个点有个权值,求最大权值-最小权值<=d的连通块个数

题解:

枚举最大权值点作为根,可以算出最小权值最小是多少,然后树形dp,每次合并两个连通块dp[u]=dp[u]+dp[u]*dp[v] (原来的方案数+加入新连通块的方案数)

树形dp中大于最大或者小于最小显然就不考虑了;

我们考虑这样计数有什么问题:两个相同权值的点当最大权值的情况,同样的连通块会算两次;

考虑怎么去重:如果v的标号>root的标号,那么就不考虑。

技术图片
 1 #include<bits/stdc++.h>
 2 #define maxn 2005
 3 #define ll long long
 4 using namespace std;
 5 const ll mod = 1000000007;
 6 int n,d;
 7 int a[maxn];
 8 struct edge
 9 {
10     int to,next;
11 }e[maxn<<1];
12 int head[maxn],p;
13 void addedge(int u,int v)
14 {
15     e[++p].to=v;e[p].next=head[u];head[u]=p;
16 }
17 ll dp[maxn];
18 void dfs(int u,int f,int minv,int maxv,int rt)
19 {
20     dp[u]=1;
21     for(int i=head[u];i;i=e[i].next)
22     {
23         int v=e[i].to;
24         if(v==f)continue;
25         if(a[v]<minv)continue;
26         if(a[v]>maxv||(a[v]==maxv&&v<rt))continue;
27         dfs(v,u,minv,maxv,rt);
28         dp[u]=(dp[u]+dp[u]*dp[v])%mod;
29     }
30 }
31 int main()
32 {
33     scanf("%d%d",&d,&n);
34     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
35     for(int i=1;i<n;++i)
36     {
37         int u,v;
38         scanf("%d%d",&u,&v);
39         addedge(u,v);
40         addedge(v,u);
41     }
42     ll ans=0; 
43     for(int u=1;u<=n;++u)
44     {
45         memset(dp,0,sizeof(dp));
46         dfs(u,0,a[u]-d,a[u],u);
47         ans+=dp[u];
48         ans%=mod;
49     }
50     printf("%I64d\n",ans);
51     return 0;
52 }
View Code

 

codeforces 486D

标签:can   计数   ret   show   pen   event   个数   原来   lap   

原文地址:https://www.cnblogs.com/uuzlove/p/10447926.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!