http://codeforces.com/contest/486/problem/D
题目大意:给出一棵树,求这棵树的满足最大点与最小点之差小于等于d的连通子图的个数。
题目分析:枚举每个点,假设当前该点就是该联通子图的最大点,进行遍历,最后将每个点的方案总数累加起来即可。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #include<cmath> #include<cctype> #include<cassert> #include<climits> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,n) for(int i=n;i;i--) #define Forp(x) for(int p=first[x];p;p=e[p].next) #define RepD(i,n) for(int i=n;i>=0;i--) #define MEM(a) memset(a,0,sizeof(a)) #define MEMI(a) memset(a,127,sizeof(a)) #define MEMi(a) memset(a,128,sizeof(a)) #define INF (2139062143) #define phiF (1000000006) #define MAXN (1000000+10) typedef long long ll; const ll mo=1000000007; struct info{ int to,next; }e[8005]; ll f[2005]; int tot,n,d,a[2005],first[10005],x,y,ans; void add(int x,int y){ tot++; e[tot].to=y; e[tot].next=first[x]; first[x]=tot; } void dfs(int mx,int u,int t){ f[u]=1; Forp (u){ int v=e[p].to; if (v==t) continue;//u 防止返回; if (a[v]>a[mx]) continue; if ((a[mx]-a[v])>d) continue; if (a[v]==a[mx]&&v<mx) continue;//避免多种情况 dfs(mx,v,u); f[u]*=f[v]+1ll; f[u]%=mo; } } int main(){ scanf("%d%d",&d,&n); For (i,n) scanf("%d",&a[i]); For (i,n-1) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } For (i,n){ dfs(i,i,-1); ans=(f[i]+ans)%mo; } printf("%d",ans); }
Codeforces 486 D Valid Sets 记忆化搜索
最新推荐文章于 2019-09-21 23:13:58 发布