CodeForces - 486D Valid Sets(树上的DP计数)

来源:互联网 发布:海外淘宝网首页 编辑:程序博客网 时间:2024/06/05 08:07

题意比较容易理解,就是树上的子树的要满足最大值减最小值大于等于D。然后求这种子树的个数。

一开始想先随便选个点作为树根然后再想DP方案,想了好久。事实上这样没法搞。其实只需要枚举点为树根然后以他为最大值去遍历下面就可以了,也不需要用数组去额外保存什么,直接用dfs的返回值。

但是这样其实会有重复的树被枚举了,对于2个可以到达的点a,b,他们的值一样,会有重复,什么意思?就是说如果a为根,可能是经过几个点(或者直接到达b)才到达了b,而如果b为根,那么他同样可以这样到达a,重复的子树就产生了。而对于不相同的2个点是不会出现可以合法的互相到达的情况的,方法是只需要规定一个方向就可以避免这个问题,比如对于相同的只能从小到大走,不能从大到小。

AC代码:

//#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdlib>#include<stack>#include<cmath>#include<queue>#include<set>#include<map>#include<ctime>#include<string.h>#include<string>#include<sstream>#include<bitset>using namespace std;#define ll long long#define ull unsigned long long#define eps 1e-11#define NMAX 200005#define MOD 1000000007#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define PI acos(-1)template<class T>inline void scan_d(T &ret){    char c;    int flag = 0;    ret=0;    while(((c=getchar())<'0'||c>'9')&&c!='-');    if(c == '-')    {        flag = 1;        c = getchar();    }    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();    if(flag) ret = -ret;}int a[2005],vis[2005];int d,w,rt;vector<int>v[2005];ll dfs(int pos){    vis[pos] = 1;    int sz = v[pos].size();    ll ret = 1;    for(int i = 0; i < sz; i++) if(!vis[v[pos][i]])    {        int u = v[pos][i];        if((w > a[u] && w - a[u] <= d) || (w == a[u] && u < rt))        {            ret = (ret+(ret*dfs(u))%MOD)%MOD;        }    }    return ret;}int main(){#ifdef GLQ    freopen("input.txt","r",stdin);//    freopen("o4.txt","w",stdout);#endif // GLQ    int n;    scanf("%d%d",&d,&n);    for(int i = 1; i <= n; i++)    {        v[i].clear();        scanf("%d",&a[i]);    }    for(int i = 1; i < n; i++)    {        int t1,t2;        scanf("%d%d",&t1,&t2);        v[t1].push_back(t2);        v[t2].push_back(t1);    }    ll ans = 0;    for(int i = 1; i <= n; i++)    {        w = a[i]; rt = i;        memset(vis,0,sizeof(vis));        ans = (ans+dfs(i))%MOD;    }    printf("%I64d\n",ans);    return 0;}


0 0