USACO12FEB Nearby Cows

题目传送门

最近做了好多“奶牛题”


完全没有思路,看了题解还有些迷

f[i][j]表示和节点\(i\)距离为\(j\)的节点的总数,\(son\)\(i\)的儿子,\(num\)为儿子的数量
则转移方程为f[i][j] = f[s][j-1] - f[i][j-2] * (num - 1)
这样可以保证不重不漏

\(DP\)顺序也要注意一下,难得没用深搜来转移

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define LL long long
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
      k = k * 10 + c - 48, c = getchar();
    return k * f;
}
int head[100010], tot;
struct zzz {
    int f, t, nex;
}e[100010 << 1];
void add(int x, int y) {
    e[++tot].t = y;
    e[tot].f = x;
    e[tot].nex = head[x];
    head[x] = tot;
}
int f[100010][21], n, k;
int main() {
    n = read(), k = read();
    for(int i = 1; i <= n - 1; ++i) {
        int x = read(), y = read();
        add(x, y); add(y, x);
    }
    for(int i = 1; i <= n; ++i)
        f[i][0] = read();
    for(int j = 1; j <= k; ++j)
        for(int i = 1; i <= n; ++i) {
            int num = 0;
            for(int s = head[i]; s; s = e[s].nex)
                f[i][j] += f[e[s].t][j-1], ++num;
            if(j > 1) f[i][j] -= f[i][j-2] * (num-1);
            else f[i][j] += f[i][0];
        }
    for(int i = 1; i <= n; ++i)
        printf("%d\n", f[i][k]);
    return 0;
}
posted @ 2019-11-14 10:40  MorsLin  阅读(92)  评论(0编辑  收藏  举报