題目鏈接:戳這裏
題目大意:給出一棵樹,樹上有點權,求這棵樹的滿足最大點權與最小點權之差小於d的連通子圖的個數。
題解:我們可以枚舉一個點作爲最大的點權向下擴展。但這樣有一個問題:點權相等的點會重複擴展。所以我們規定點權相等的點,只能由編號小的向編號大的點擴展。
代碼:
#include<bits/stdc++.h>
#define maxn 200005
#define maxm 400005
#define mod 1000000007
using namespace std;
typedef long long LL;
int read()
{
char c;int sum=0,f=1;c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
return sum*f;
}
int n,d;
int head[maxn],to[maxm],nex[maxm],val[maxn],cnt;
void add(int u,int v)
{
to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt;
}
LL ans;
LL dfs(int x,int fa,int lim)
{
LL ret=1;
for(int i=head[x];i;i=nex[i])
{
if(to[i]==fa || val[to[i]]>val[lim] || (val[to[i]]==val[lim] && to[i]>lim) || val[lim]-val[to[i]]>d)
continue;
ret=ret*(dfs(to[i],x,lim)+1)%mod;
}
return ret;
}
int main()
{
d=read();n=read();
for(int i=1;i<=n;i++) val[i]=read();
for(int i=1;i<n;i++)
{
int u=read(),v=read();
add(u,v);add(v,u);
}
for(int i=1;i<=n;i++)
ans+=dfs(i,-1,i),ans%=mod;
cout<<ans<<endl;
return 0;
}