Description
里口福因有林下风气,带领全国各地高校掀起了一股AK风,大家都十分痴迷于AK。里口福为了打击大家的自信心,出了一道自以为十分困难的题目。
里口福有一棵树,第i个节点上有点权ai,他的问题就是这棵树中有多少个不同的连通块满足连通块的最大值与最小值之差=k,两个连通块不同当且仅当至少存在一个节点在一个连通块中出现而另一个连通块中没有出现。
痴迷于AK的你马上接下这道题目,在里口福狂妄的笑声中,你切掉这道题的决心更加坚定了,现在就差你的代码了。
里口福有一棵树,第i个节点上有点权ai,他的问题就是这棵树中有多少个不同的连通块满足连通块的最大值与最小值之差=k,两个连通块不同当且仅当至少存在一个节点在一个连通块中出现而另一个连通块中没有出现。
痴迷于AK的你马上接下这道题目,在里口福狂妄的笑声中,你切掉这道题的决心更加坚定了,现在就差你的代码了。
Input
第一行两个整数n,k,表示树的大小以及题目中的k。
第二行n个整数,第i个整数表示ai。
接下来n-1行,每行两个整数x,y表示树边(x,y)。
第二行n个整数,第i个整数表示ai。
接下来n-1行,每行两个整数x,y表示树边(x,y)。
Output
一行一个整数,表示答案,答案对19260817取模。
Sample Input
5 3 1 2 3 4 5 1 2 1 3 2 4 2 5
Sample Output
4
Data Constraint
对于30%的数据,n<=22
对于另外20%的数据,树是一条链
对于另外20%的数据,ai只有0和1两种
对于100%的数据,N<=3333,0<=ai<=N,K>=0
对于另外20%的数据,树是一条链
对于另外20%的数据,ai只有0和1两种
对于100%的数据,N<=3333,0<=ai<=N,K>=0
做法:有一个套路,所有差值<=k的联通块减去<=k-1的联通块即是答案,可以用树形dp统计。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define mo 19260817 5 #define N 7777 6 #define LL long long 7 using namespace std; 8 int n,m,ls[N],tot; 9 LL ans,ans2; 10 struct edge{ 11 int to,next; 12 }e[N]; 13 14 struct arr{ 15 int s,num; 16 }a[N]; 17 18 void add(int x,int y){ 19 e[++tot].to=y; 20 e[tot].next=ls[x]; 21 ls[x]=tot; 22 } 23 24 void Init(){ 25 scanf("%d%d",&n,&m); 26 for (int i=1;i<=n;i++) scanf("%d",&a[i].s),a[i].num=i; 27 for (int i=1;i<n;i++){ 28 int u,v; 29 scanf("%d%d",&u,&v); 30 add(u,v); 31 add(v,u); 32 } 33 } 34 35 LL count(int x,int pre,int root){ 36 LL sum=1; 37 for (int i=ls[x];i;i=e[i].next){ 38 int v=e[i].to; 39 if (v==pre) continue; 40 if (a[root].s-a[v].s>m||a[root].s<a[v].s) continue; 41 if (a[root].s==a[v].s&&a[root].num<a[v].num) continue; 42 sum=(sum*(count(v,x,root)+1))%mo; 43 } 44 return sum; 45 } 46 47 48 LL count2(int x,int pre,int root){ 49 LL sum=1; 50 for (int i=ls[x];i;i=e[i].next){ 51 int v=e[i].to; 52 if (v==pre) continue; 53 if (a[root].s-a[v].s>m-1||a[root].s<a[v].s) continue; 54 if (a[root].s==a[v].s&&a[root].num<a[v].num) continue; 55 sum=(sum*(count2(v,x,root)+1))%mo; 56 } 57 return sum; 58 } 59 60 61 int main(){ 62 freopen("lkf.in","r",stdin); 63 freopen("lkf.out","w",stdout); 64 Init(); 65 for (int i=1;i<=n;i++) 66 ans=(ans+count(i,0,i))%mo; 67 if (m!=0){ 68 for (int i=1;i<=n;i++) 69 ans2=(ans2+count2(i,0,i))%mo; 70 } 71 cout<<(ans-ans2+mo)%mo; 72 }