正题
题目大意
求一棵树上有多少个联通块的最大值和最小值差为k。
解题思路
其实直接用差<=k的减去差<k的就是等于k的答案。
然后枚举一个点为最大值,然后只往小编号扩张就好了(不重)。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 4000
#define XJQ 19260817
#define ll long long
using namespace std;
struct node{ll to,next;
}a[N*2];
ll ls[N],w[N],ans1,ans2,n,k,tot,x,y,in[N];
void addl(ll x,ll y)//加边
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
ll dp(ll x,ll fa,ll root,ll W)//dp
{ll rep=1;for(ll i=ls[x];i;i=a[i].next){int v=a[i].to;if(v==fa||w[a[i].to]>w[root]) continue;if(w[root]-w[v]>W) continue;if(v<root||w[v]<w[root])rep=(rep*(dp(v,x,root,W)+1)%XJQ)%XJQ;}return rep;
}
int main()
{scanf("%lld%lld",&n,&k);for(ll i=1;i<=n;i++)scanf("%lld",&w[i]);for(ll i=1;i<n;i++){scanf("%lld%lld",&x,&y);addl(x,y);addl(y,x);}for(ll i=1;i<=n;i++){ans1=(ans1+dp(i,i,i,k))%XJQ;if(k) ans2=(ans2+dp(i,i,i,k-1))%XJQ;}printf("%lld",(ans1-ans2+XJQ)%XJQ);
}