zoukankan      html  css  js  c++  java
  • luogu P3047 [USACO12FEB]附近的牛Nearby Cows

    银月城传送门

    树形dp+1

    状态好想得不得了:定义f[i][j]为i点在j步以内的所有奶牛数

    转移方程的初步形式也很容易得出来:f[i][j]=sum(f[s][j-1])

    但是这样会有一个问题,如果j>1,对于每个子结点s,都有继续向下推下去,但这样显然会重复累加一些边。

    所以需要减去重复累加的边:f[i][j]=sum(f[s][j])-(f[i][j-2]*(子结点个数-1)  (-1是因为要加一次)

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    struct EDge
    {
        int to,br;
    }bian[210005];
    int son[100005],len,f[100005][25],sons[100005],n,k;
    
    void add(int a,int b)
    {
        bian[++len].to=b;
        bian[len].br=son[a];
        son[a]=len;
        bian[++len].to=a;
        bian[len].br=son[b];
        son[b]=len;
        sons[a]++; 
        sons[b]++;
    }
    
    int main()
    {
        int i,j,s;
        scanf("%d%d",&n,&k);
        for(i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(i=1;i<=n;i++)
        scanf("%d",&f[i][0]);
        for(j=1;j<=k;j++)
            for(i=1;i<=n;i++)
            {
                for(s=son[i];s;s=bian[s].br)
                f[i][j]+=f[bian[s].to][j-1];
                if(j>1)
                f[i][j]-=(sons[i]-1)*f[i][j-2];
                else 
                f[i][1]+=f[i][0]; 
            }
        for(i=1;i<=n;i++)
        printf("%d
    ",f[i][k]);
        return 0;
    }
  • 相关阅读:
    [LeetCode 220.] 存在重复元素 III
    C++ 构造函数 & 析构函数
    [LeetCode 891.] 子序列宽度之和【hard】
    [LeetCode 447.] Number of Boomerangs
    HJ93 数组分组
    HJ77 火车进站
    [LeetCode 338.] 比特位计数
    线段树
    大数量问题的一般解决方法
    字典树
  • 原文地址:https://www.cnblogs.com/charlesss/p/10338663.html
Copyright © 2011-2022 走看看