http://codeforces.com/contest/486/problem/D
题意:给定一棵树,点上有权值,以及d,要求有多少种联通块满足最大值减最小值小于等于d。
思路:枚举i作为最大的点权,然后dfs树规一下,就能得出以这个点为最大值的方案数,因为有权值相等的点,所以我们规定一下,只能从标号小的拓展到标号大的,就不会重复了。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define ll long long 7 const ll Mod=1000000007; 8 int tot,go[200005],first[200005],next[200005],a[200005],d,n; 9 ll f[200005]; 10 int read(){ 11 int t=0,f=1;char ch=getchar(); 12 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 13 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 14 return t*f; 15 } 16 void insert(int x,int y){ 17 tot++; 18 go[tot]=y; 19 next[tot]=first[x]; 20 first[x]=tot; 21 } 22 void add(int x,int y){ 23 insert(x,y);insert(y,x); 24 } 25 void dfs(int x,int fa,int fi){ 26 f[x]=1; 27 for (int i=first[x];i;i=next[i]){ 28 int pur=go[i]; 29 if (pur==fa) continue; 30 if (a[pur]>a[fi]) continue; 31 if (a[fi]-d>a[pur]) continue; 32 if (a[fi]==a[pur]&&fi>pur) continue; 33 dfs(pur,x,fi); 34 f[x]*=(1LL+f[pur]); 35 f[x]%=Mod; 36 } 37 } 38 int main(){ 39 d=read();n=read(); 40 for (int i=1;i<=n;i++) 41 a[i]=read(); 42 for (int i=1;i<n;i++){ 43 int x=read(),y=read(); 44 add(x,y); 45 } 46 ll ans=0; 47 for (int i=1;i<=n;i++){ 48 for (int j=1;j<=n;j++) f[j]=0; 49 dfs(i,0,i); 50 ans=(ans+f[i])%Mod; 51 } 52 printf("%I64d\n",ans); 53 }