【链接】 我是链接,点我呀:)

【题意】

问你一棵树上有多少条长度为k的路径

【题解】

树形dp

size[i]表示以节点i为根节点的子树的节点个数
dp[i][k]表示以i为根节点的子树里面距离节点i的距离为k的节点有多少个.
长度为k的路径有两种情况.
1.这个路径从x开始,只经过x的一个子树.
2.这个路径经过x,横跨x的两个子树.
第一种情况直接累加dp[x][k]即可
第二种情况,可以枚举其中一棵子树y包括的路径长度i,另外一棵子树(其余size[x]-1棵子树都可以作为另外一棵子树)
自然包括的路径长度就是k-i了
累加0.5*dp[y][i-1]*(dp[x][k-i]-dp[y][k-i-1]);
乘0.5是因为把(x,y)和(y,x)都算一遍
(dp[x][k-i]-dp[y][k-i-1])表示的是除去y子树其余size[x]-1棵子树中和x距离为k-i的节点个数
具体的代码中有注释

【代码】

import java.io.*;
import java.util.*; public class Main { static InputReader in;
static PrintWriter out; public static void main(String[] args) throws IOException{
//InputStream ins = new FileInputStream("E:\\rush.txt");
InputStream ins = System.in;
in = new InputReader(ins);
out = new PrintWriter(System.out);
//code start from here
new Task().solve(in, out);
out.close();
} static int N = 50000;
static int K = 500;
static class Task{
long [][]dp;
long ans;
ArrayList []g;
int n,k; void dfs(int x,int fa) {
dp[x][0] = 1;
int len = g[x].size();
for (int i = 0;i < len;i++) {
int y = (int)g[x].get(i);
if (y==fa) continue;
dfs(y,x);
for (int j = 1;j <= k;j++) {
dp[x][j] = dp[x][j] + dp[y][j-1];
}
}
//以x为开始的链
ans = ans + dp[x][k]; //跨过两颗子树
long ans2 = 0;
if (k>=2)//只有长度大于等于2才可能跨过两棵子树
for (int i = 0;i < len;i++) {
int y = (int)g[x].get(i);
if (y==fa) continue;
//以子树y的某个节点作为起点,然后到达x再到达其他位置
for (int l = 1;l<=k-1;l++) {//不能全都在这棵子树里面,得留k-l在另外一个子树
//l是x到y下面的某个节点的长度,比如l=1那么就是到达y节点
//从y的话就是往下l-1长度的点
long temp1 = dp[y][l-1]; //紧接着要找从x出发长度为k-l的点(不能包括y这棵子树)
long temp2 = dp[x][k-l]-dp[y][k-l-1];
ans2 = ans2 + temp1*temp2;
}
}
ans2/=2;//每种都会重复算一次
ans = ans + ans2;
} public void solve(InputReader in,PrintWriter out) {
dp = new long[N+10][K+10];
g = new ArrayList[N+10];
for (int i = 1;i<= N;i++) g[i] = new ArrayList(); n = in.nextInt(); k = in.nextInt(); for (int i = 1;i <= n-1;i++) {
int x,y;
x = in.nextInt();y = in.nextInt();
g[x].add(y);g[y].add(x);
} dfs(1,-1);
out.println(ans);
}
} static class InputReader{
public BufferedReader br;
public StringTokenizer tokenizer; public InputReader(InputStream ins) {
br = new BufferedReader(new InputStreamReader(ins));
tokenizer = null;
} public String next(){
while (tokenizer==null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(br.readLine());
}catch(IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
} public int nextInt() {
return Integer.parseInt(next());
}
}
}

【Codeforces 161D】Distance in Tree的更多相关文章

  1. 【27.91%】【codeforces 734E】Anton and Tree

    time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  2. 【codeforces 791D】 Bear and Tree Jumps

    [题目链接]:http://codeforces.com/contest/791/problem/D [题意] 你可以从树上的节点一次最多走k条边. (称为跳一次); 树为无权树; 然后问你任意两点之 ...

  3. 【树形dp】Distance in Tree

    [CF161.D] Distance in Tree time limit per test 3 seconds memory limit per test 512 megabytes A tree  ...

  4. 【19.27%】【codeforces 618D】Hamiltonian Spanning Tree

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  5. 【27.48%】【codeforces 699D】 Fix a Tree

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  6. 【Codeforces 1086B】Minimum Diameter Tree

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 统计叶子节点个数m 把每条和叶子节点相邻的边权设置成s/cnt就可以了 这样答案就是2*s/m(直径最后肯定是从一个叶子节点开始,到另外一个叶 ...

  7. 【codeforces 698B】 Fix a Tree

    题目链接: http://codeforces.com/problemset/problem/698/B 题解: 还是比较简单的.因为每个节点只有一个父亲,可以直接建反图,保证出现的环中只有一条路径. ...

  8. 【CodeForces 699D】Fix a Tree

    dfs找出联通块个数cnt,当形成环时,令指向已访问过节点的节点变成指向-1,即做一个标记.把它作为该联通图的根. 把所有联通的图变成一颗树,如果存在指向自己的点,那么它所在的联通块就是一个树(n-1 ...

  9. 【CodeForces 614A】Link/Cut Tree

    题 题意 给你一个区间,求里面有多少个数是k的次方. 分析 暴力,但是要注意这题范围会爆long long,当k=1e8: l=1:r=1e18时 k²=1e16,判断了是≤r,然后输出,再乘k就是1 ...

随机推荐

  1. 布局技巧2:合并布局(merge标签)

    我们已经有文章向你描述如何使用<include />标签来重用和共享你的布局代码.这篇文章将向你阐述<merge />标签的使用以及如何与<include />标签 ...

  2. bzoj3940

    AC自动机 复习一下... 可惜又写错了 我们发现就是把单词建成ac自动机,然后把串在ac自动机上跑一遍,每到一个单词结束点就删除,删除是利用栈,每次弹出单词长度个字符就可以了 发现两个小问题,str ...

  3. 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)

    上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...

  4. Spring思维课程导图——bean得实例化和bean的管理

  5. Java编程思想读书笔记_第二章

    java对于将一个较大作用域的变量“隐藏”的场景会有保护:编译告警.比如: int x = 5; { int x = 6; } 但是对于类中方法的局部变量和类成员变量确是可以重名的,比如 class ...

  6. css文本背景样式

    文本样式 文本类 text-transform:uppercase: 全部变为大写 text-transform:lowercase: 全部变为小写 text-transform:capitalize ...

  7. javascript DOM编程艺术 第10章问题记录

    为什么moveElement函数调用时,必须加字符串的拼接符 var repeat = "moveElement('"+elementID+"',"+final ...

  8. Java&Xml教程(二)使用DOM方式解析XML文件

    DOM XML 解析方式是最容易理解的,它將XML文件作为Document对象读取到内存中,然后你可以轻松地遍历不同的元素和节点对象.遍历元素和节点不需要按照顺序进行. DOM解析方式适合尺寸较小的X ...

  9. PHP魔术法__set和__get

    __set: 在给不可访问属性赋值时,__set() 会被调用.语法如下: public void __set ( string $name , mixed $value ) __get: 读取不可访 ...

  10. Burn Down Chart(2018.6.4~2018.6.10)

    Burn Down Chart (2018.6.4~2018.6.10) 娄雨禛[前端部分] 曾子轩[后端部分+燃尽图] 前端 1. 娄雨禛+李鑫 1)在总工程中完成跳转,实现图片显示,并发布到Git ...