zoukankan      html  css  js  c++  java
  • 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;    
    }
  • 相关阅读:
    MathType中如何快速输入空心字母
    如何用MathType编辑出积分符号
    史上“最骚”公式编辑器,你了解多少!
    几何画板中直角符号为什么不带阴影
    mssql 版本查询
    python爬取网站数据保存使用的方法
    sql 联合查询
    sql join
    增删改查
    发送json-简单的传参查询和简单的sql查询
  • 原文地址:https://www.cnblogs.com/staginner/p/2711565.html
Copyright © 2011-2022 走看看