CF 161D Distance in Tree 树形DP

博客探讨了如何使用树形动态规划解决无根树中节点间距离为K的节点对计数问题。通过将无根树转换为有根树,统计每个子树内节点对的距离,并考虑重叠部分进行去重,从而得出答案。
摘要由CSDN通过智能技术生成

题意:给出一个无根树,统计有多少节点对之前的距离恰好等于K。相邻节点间的距离为1.
思路:树形DP。
我们可以将无根树转化成有根树,这个很容易做到。
对于一个子树,其根结点为s,我们只需统计s的子树之间距离为K节点对即可。然后对每个子树都进行相同的统计,就可以得到最终的答案。
因为这些节点对是经过根结点s,所以他们和根结点的距离之和就是K。所以我们要知道在以s为根的子树下,有多少个距离为i的节点。然后在利用计数的乘法原理就可以了。
但是还要考虑的一个问题是如何去重。只是简单的统计出节点s的所有儿子的距离分布,会让我们丧失太多的信息,因为我们不知道这些儿子位于哪棵子树中。因为求节点s的所有儿子的距离的时候,是按照一个一个子树来求的,这个过程已经非常自然的帮我们把子树划分开。所以,我们要在这个过程中先求出当前子树和前面所有子树产生了多少满足条件的节点对,再把当前子树的节点加入到根结点上。

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int MAX = 50010;

int N,K;
int to[MAX*2],nxt[MAX*2],head[MAX],tot;
long long s[50010][510];

void init()
{
    memset(head,-1,sizeof(head));
    tot = 0;
}
void addedge(int u, int v)
{
    to[tot] = v, nxt[tot] = head[u];
    head[u] = tot++;
    to[tot] = u, nxt[tot] = head[v];
    head[v] = tot++;
}

long long dfs(int u, int p)
{
    s[u][0] = 1;
    long long ans = 0;
    for(int i = head[u]; ~i ; i = nxt[i]){
        int v = to[i];
        if(p == v) continue;
        ans += dfs(v,u);
        for(int i = 0; i < K; ++i)
            ans += s[u][i] * s[v][K - i - 1];
        for(int i = 1; i < K; ++i)
            s[u][i] += s[v][i-1];
    }
    return ans;
}


int main(void)
{
    //freopen("input.txt","r",stdin);
    init();
    scanf("%d%d",&N,&K);
    for(int i = 0; i < N - 1; ++i){
        int u, v;
        scanf("%d%d",&u,&v);
        addedge(u,v);
    }
    printf("%I64d\n",dfs(1,0));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值