• BZOJ 2591 [Usaco 2012 Feb]Nearby Cows


    BZOJ_2591

        由于K比较小,我们可以用f[i][j]表示距离第i个节点为j的所有节点的权值和,那么最后实际上就是对于特定的i输出sum{f[i][j]}。

        对于一个特定的f[i][j]来讲,一共由两部分构成,一部分路径来自于子节点,一部分路径来自于父节点,我们可以先从叶子节点开始向上dp,将来自于子节点的部分计算出来,再从根节点开始向下dp,将来自于父节点的部分累加上。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 100010
    #define MAXM 200010
    int N, K, first[MAXD], e, next[MAXM], v[MAXM], c[MAXD];
    int f[MAXD][25], dp[MAXD][25];
    void add(int x, int y)
    {
        v[e] = y;
        next[e] = first[x], first[x] = e ++;    
    }
    void init()
    {
        memset(first, -1, sizeof(first[0]) * (N + 1)), e = 0;
        for(int i = 1; i < N; i ++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y), add(y, x);
        }
        for(int i = 1; i <= N; i ++) scanf("%d", &c[i]);
    }
    int q[MAXD], fa[MAXD];
    void solve()
    {
        int rear = 0;
        q[rear ++] = 1, fa[1] = -1;
        for(int i = 0; i < rear; i ++)
        {
            int x = q[i];
            for(int j = first[x]; j != -1; j = next[j])
                if(v[j] != fa[x])
                    fa[v[j]] = x, q[rear ++] = v[j];
        }
        for(int i = rear - 1; i >= 0; i --)
        {
            int x = q[i];
            memset(f[x], 0, sizeof(f[x][0]) * (K + 1));
            for(int j = first[x]; j != -1; j = next[j])
                if(v[j] != fa[x])
                    for(int k = 1; k <= K; k ++)
                        f[x][k] += f[v[j]][k - 1];
            f[x][0] = c[x];
        }
        for(int i = 0; i < rear; i ++)
        {
            int x = q[i];
            for(int j = first[x]; j != -1; j = next[j])
                if(v[j] != fa[x])
                {
                    int y = v[j];
                    for(int k = K; k >= 1; k --)
                        f[y][k] += f[x][k - 1] - (k > 1 ? f[y][k - 2] : 0);    
                }
        }
        for(int i = 1; i <= N; i ++)
        {
            int ans = 0;
            for(int j = 0; j <= K; j ++) ans += f[i][j];
            printf("%d\n", ans);    
        }
    }
    int main()
    {
        while(scanf("%d%d", &N, &K) == 2)
        {
            init();
            solve();    
        }
        return 0;    
    }
  • 相关阅读:
    CentOS 6.5下快速搭建ftp服务器
    Ubuntu增加swap交换空间的步骤
    mysql官方下载安装教程(centos)
    阿里云上遇到: virtual memory exhausted: Cannot allocate memory
    解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed错误
    centos安装nodejs和配置npm
    JavaScript(二)-精简
    JavaScript(一)
    ease,seae-in,ease-in-out,ease-out区别
    安装 sass 文档
  • 原文地址:https://www.cnblogs.com/staginner/p/2711565.html
Copyright © 2020-2023  润新知