[USACO12FEB]Nearby Cows

题意

给出一棵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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值