2018年10月30日提高组 T1 A

版权声明:转载无所谓的。。。 https://blog.csdn.net/xuxiayang/article/details/83545016

大意

求树上联通快中最大值与最小值之差为 k k 的方案数


思路

设最大值与最小值之差为 x x

x x 正好为 k k 的方案数 = x k =x\leq k 的方案数- x < k x<k 的方案数

于是我们就可以树形 d p dp

f i = ( f s o n + 1 ) f_i=\prod (f_{son}+1)


大意

#include<cstdio>
#define mod 19260817
using namespace std;
typedef long long LL;int l[3501],n,k,tot,v[3501];
struct node{int next,to;}e[7001];
inline void add(register int u,register int v){e[++tot]=(node){l[u],v};l[u]=tot;return;}
LL ans;
inline LL dp(register int x,register int fa,register int mx)
{
	long long ass=1;
	for(register int i=l[x];i;i=e[i].next)
	if(v[mx]>=v[e[i].to]&&v[mx]-v[e[i].to]<=k&&e[i].to!=fa&&(v[e[i].to]!=v[mx]||e[i].to>mx))//必须满足限制并且不往走,同时处理同组解的情况
	(ass*=dp(e[i].to,x,mx)+1)%=mod;//计算
	return ass;//返回
}
signed main()
{
	scanf("%d%d",&n,&k);
	for(register int i=1;i<=n;i++) scanf("%d",v+i);//输入
	for(register int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);//输入
	for(register int i=1;i<=n;i++) (ans+=dp(i,0,i))%=mod;//计算
	if(k==0) return printf("%lld",ans%mod)&0;//特判
	k--;//计算k-1
	for(register int i=1;i<=n;i++) (ans=ans-dp(i,0,i)+mod)%=mod;//计算
	printf("%lld",ans);//输出
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/83545016