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;
}