CodeForces 486D Valid Sets

来源:互联网 发布:出国旅游英语翻译软件 编辑:程序博客网 时间:2024/06/01 09:06

题意:

给定一棵n(2000)个节点的树  每个节点上有个数字  问  有多少棵子树满足树中最大数字与最小数字的差不超过d

思路:

根据数据猜复杂度可能为n^2  想到尝试树形dp

假如枚举现在树中的最大值  那么最小值可以求出  这时不在数值范围内的节点都可以标记掉

那么假设这个最大值的点我一定选取  那么就可以dp出一定选这个点的情况下子树的种类数

假设u是父节点  v是子节点  那么已知dp[u]=dp[u]*dp[v]  特殊的v如果是叶子  那么dp[v]=2  即可选可不选  如果u是不是根  那么dp[u]最后要+1  因为可以不选u

我们发现这样dp还是不可以的  因为假设现在枚举的最大值为10  树中可能有两个10的节点是连通的  这时计数就会出问题  不过没关系  我们刚才的定义是“一定选某个点”  那么假设我们dp算过了“一定选一号10节点”的情况  这时就可以把一号10节点标记成坏节点  下次处理二号10节点的时候就可以一定不选刚才的点了

代码:

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<map>#include<set>#include<vector>#include<queue>#include<cstdlib>#include<ctime>#include<cmath>using namespace std;typedef long long LL;#define N 2010#define mod 1000000007int n, d, m, big, small;int val[N], a[N], vis[N];struct edge {    int v, next;} ed[N * 2];int head[N], tot;LL dp[N], ans;void add(int u, int v) {    ed[tot].v = v;    ed[tot].next = head[u];    head[u] = tot++;}void dfs(int u, int key) {    vis[u] = 1;    dp[u] = 1;    for (int i = head[u]; ~i; i = ed[i].next) {        int v = ed[i].v;        if (!vis[v]) {            dfs(v, 1);            dp[u] = (dp[u] * dp[v]) % mod;        }    }    dp[u] = (dp[u] + key) % mod;    vis[u] = 0;}int main() {    scanf("%d%d", &d, &n);    for (int i = 1; i <= n; i++) {        scanf("%d", &val[i]);        a[i] = val[i];        head[i] = -1;    }    tot = 0;    for (int i = 2; i <= n; i++) {        int u, v;        scanf("%d%d", &u, &v);        add(u, v);        add(v, u);    }    sort(a + 1, a + n + 1);    m = unique(a + 1, a + n + 1) - a - 1;    for (int i = m; i >= 1; i--) {        big = a[i];        small = big - d;        for (int j = 1; j <= n; j++) {            if (val[j] < small || val[j] > big)                vis[j] = 1;            else                vis[j] = 0;        }        for (int j = 1; j <= n; j++) {            if (!vis[j] && val[j] == big) {                dfs(j, 0);                ans = (ans + dp[j]) % mod;                vis[j] = 1;            }        }        //cout << a[i] << " " << ans << endl;    }    cout << ans << endl;    return 0;}


0 0
原创粉丝点击