[USACO12FEB]Nearby Cows

来源:互联网 发布:于丹 知乎 编辑:程序博客网 时间:2024/06/03 15:47

题意

给出一棵n个点的无根树,每个点有权值,问每个点向外不重复经过k条边的点权和


题解

设f[i][j]表示所有离i节点距离为j的点权和,v为它周围相邻的点,t为v的个数,则
j > 2 f[i][j] = (sigma f[v][j - 1]) - (t - 1) * f[i][j - 2]
j==2 f[i][j] = (sigma f[v][j - 1]) - t * f[i][j - 2]
枚举j,再Dfs即可。


常数巨大的丑陋代码

# include <stdio.h># include <stdlib.h># include <iostream># include <string.h># include <math.h>using namespace std;# define IL inline# define RG register# define UN unsigned# define ll long long# define rep(i, a, b) for(RG int i = a; i <= b; i++)# define per(i, a, b) for(RG int i = b; i >= a; i--)# define uev(e, u) for(RG int e = ft[u]; e != -1; e = edge[e].nt)# define mem(a, b) memset(a, b, sizeof(a))# define max(a, b) ((a) > (b)) ? (a) : (b)# define min(a, b) ((a) < (b)) ? (a) : (b)IL int Get(){    RG char c = '!'; RG int num = 0, z = 1;    while(c != '-' && (c > '9' || c < '0')) c = getchar();    if(c == '-') z = -1, c = getchar();    while(c >= '0' && c <= '9') num = num * 10 + c - '0', c = getchar();    return num * z;}const int MAXN = 100001, INF = 2147483647;struct Edge{    int to, nt;} edge[MAXN << 1];int n, cnt, ft[MAXN], k, f[MAXN][21], sum[MAXN];IL void Add(RG int u, RG int v){    edge[cnt] = (Edge){v, ft[u]}; ft[u] = cnt++;}IL void Dfs(RG int u, RG int fa, RG int d){    RG int t = 0;    uev(e, u){        RG int v = edge[e].to;        t++; f[u][d] += f[v][d - 1];        if(v == fa) continue;        Dfs(v, u, d);    }    if(d == 2) f[u][d] -= t * f[u][0];    if(d > 2) f[u][d] -= (t - 1) * f[u][d - 2];    sum[u] += f[u][d];}int main(){    mem(ft, -1);    n = Get(); k = Get();    rep(i, 1, n - 1){        RG int u = Get(), v = Get();        Add(u, v); Add(v, u);    }    rep(i, 1, n) sum[i] = f[i][0] = Get();    rep(i, 1, k) Dfs(1, 0, i);    rep(i, 1, n) printf("%d\n", sum[i]);    return 0;}