码迷,mamicode.com
首页 > 其他好文 > 详细

【XSY2411】【CF161D】Distance in Tree

时间:2019-10-02 12:58:29      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:+=   练习题   line   NPU   getchar   ons   c++   端点   ++   

\(Description\)

一棵树是一个不含环的连通图。

树上两点间的距离是两点间最短路径的长度(边的)。

给你一棵\(n\)个点的树和一个正整数\(k\)。找出不同的距离为\(k\)的点对的数量。注意点对\((u,v)\)\((v,u)\)被认为是相同的。


\(Input\)

第一行包含两个整数\(n\)\(k\) \((1≤n≤50000,1≤k≤500)\)——点数和要求的两点间距离。

接下来\(n-1\)行代表了边\(“a_{i}\) \(b_{i}”\)(没有引号)\((1≤a_{i},b_{i}≤n,a_{i}≠b_{i})\)\(a_{i}\)\(b_{i}\)是第\(i\)条边的端点。所有给出的边都是不同的。


\(Output\)

输出单独一个整数——不同的距离正好为\(k\)的树上点对的数量。


\(Sample Input\)

样例输入1
5 2
1 2
2 3
3 4
2 5

样例输入2
5 3
1 2
2 3
3 4
4 5


\(Sample Output\)

样例输出1
4

样例输出2
2


\(HINT\)

第一个样例的距离为\(2\)的点对是\((1,3)\)\((1,5)\)\((3,5)\)\((2,4)\)


\(Source\)

 练习题 树1-树形DP

思路

我们考虑计算出对于以\(u\)为根的子树中,距离\(u\)各种距离的节点的个数,这个值可以通过\(u\)的儿子\(v\)来更新

所以我们选择树形\(dp\)

我们设一个数组\(sum[u][t]\),表示以\(u\)为根的子树中,距离\(u\)的距离为\(t\)的节点的个数

那么答案\(ans\)就是\(\sum_{j=0}^{k-1}sum[u][j]\times sum[v][k-j-1]\)

这个简单解释下:枚举与\(u\)距离\(j\)的点,因为要统计距离为\(k\)的点个数,于是我们还需要距离\(k-j\)的点,因为通过\(v\)转移 ,有一个距离\(1\),所以只需要找与\(v\)距离\(k-j-1\)的点的个数,乘起来就可以了

接下来,来讲讲怎么转移方程

也十分简单:\(\sum_{j=1}^{k}sum[u][j]+=sum[v][j-1]\)

很好理解那就不细讲了

于是我们就可以一遍\(dfs\)处理出\(sum\)数组和答案,最后直接输出就好了


代码

#include<bits/stdc++.h>
using namespace std;
const int N=50010;
int n,k,cnt=0;
int to[N<<1],nxt[N<<1],head[N];
int sum[N][510];
int ans=0;
inline void add(int u,int v)
{
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa)
{
    sum[u][0]=1;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(v==fa)continue;
        dfs(v,u);
        for(int j=0;j<k;j++)ans+=sum[u][j]*sum[v][k-j-1];
        for(int j=1;j<=k;j++)sum[u][j]+=sum[v][j-1];
    }
}
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int main()
{
    n=read(),k=read();
    int a,b;
    for(int i=1;i<n;i++)
    {
        a=read(),b=read();
        add(a,b);add(b,a);
    }
    dfs(1,0);
    printf("%d",ans);
    return 0;
}

【XSY2411】【CF161D】Distance in Tree

标签:+=   练习题   line   NPU   getchar   ons   c++   端点   ++   

原文地址:https://www.cnblogs.com/ShuraEye/p/11617056.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!