题目链接:http://codeforces.com/contest/791/problem/D

题意:给出一棵树,每两个点之间的距离为1,一步最多可以走距离 k,问要将任意两个点之间的路径都走一遍,最少需要走多少步;

思路:对于不是很简单的问题我们可以将问题分解成若干步或许会简单一点,对于本题我们可以先考虑只求所有路径的距离之和, 假设我们求得其值为ans;不过因为有些路径的长度并不是m的整倍数,所以我们不能直接用ans/m得到答案;不过如果我们能找到所有不是m的整倍数的路径并且可以求出其%m的值的话,那么我们可以给其补上一个尽量小的数并使其能整除m, 那么我们只要将所有补加的数累加到ans里面去,那么ans/m就是我们要的答案啦。。。

接下来我们需要考虑一下具体如何实现上面两步:

对于如何求得ans,我们可以计算出对于每条边经过他的路径数,就是这条边对ans的贡献值,那么累加对于每条边经过她的路径数就是ans啦;每条边都是由相邻的两个节点构成的,我们可以将两个节点看做父子节点,那么经过这条边的路径的数目为son*(n-son),其中son为子节点所在的子树的大小,那么n-son就是子树外的节点数目(这个应该挺好理解的,不理解的画下图就明白了);显然我们只要dfs搜一遍就能得到ans啦;

下面我们只要求出长度%m不为整数的路径就ok了。我们不防这样想,从某点出发的所有路径中任选两条可以组成一条经过该点的路径,那么所有组合即为所有经过该点的路径。

我们用dp[i][j]记录从点 i 出发%m为 j 的路径的数目,那么我们可以同过 j 的组合得到经过点 i 长度%m=j'的路径数目,显然只要求出dp[i][j]我们很容易得到补加的的值是多少。

若对于当前节点i, 我们已知dp[i][j],那么显然对于其父节点有 dp[i'][(j+1)] = dp[i][j],所以我们我们可以在dfs回溯时通过dp计算出dp[i][j]的值;对叶子节点初始化为dp[i][0]=1;

至此已经圆满解决这个问题啦。。

代码:

 #include <iostream>
#include <stdio.h>
#include <vector>
#define ll long long
using namespace std; const int MAXN=2e5+;
int n, m;
bool vis[MAXN];//标记当前节点是否搜过
vector<int> mp[MAXN];
ll dp[MAXN][], son[MAXN], ans=;//dp[i][j]存储以i为根节点,i的子树中距离i长度mod k==j的的路径的条数,son[i]记录i的子树大小 void dfs(int point){
son[point]=;//相当于将两个数组初始化为 1
dp[point][]=;
for(int i=; i<mp[point].size(); i++){
int v=mp[point][i];
if(!vis[v]){
vis[v]=true;
dfs(v);
son[point]+=son[v];//将子树中节点的数目加到当前节点上
ans+=(son[v])*(ll)(n-son[v]);//统计经过边[point,i]的路径数目
for(int j=; j<m; j++){
for(int k=; k<m; k++){
if((j+k+)%m){
ans+=dp[point][j]*dp[v][k]*(ll)(m-(j+k+)%m);//i+j+k为分别由点point,及一个其子节点引出的路径长度%m再求和
}
}
}
for(int j=; j<m; j++){
dp[point][(j+)%m]+=dp[v][j];//从节点mp[point][i]回溯到其父节点,那么由原来mp[point][i]的子树到其的距离%m=j的路径数目转移得到point的子树到其距离+1%m=j的路径数目
}
}
}
} int main(void){
scanf("%d%d", &n, &m);
for(int i=; i<n; i++){
int x, y;
scanf("%d%d", &x, &y);
mp[x].push_back(y);
mp[y].push_back(x);
}
vis[]=true;
dfs();
printf("%lld\n", ans/m);
return ;
}

719D(树形dp)的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  3. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  4. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  5. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  6. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  7. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

  8. hdu1561 The more, The Better (树形dp+背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...

  9. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

随机推荐

  1. win7计划任务定时执行PHP脚本设置图解

    做php开发的朋友有时候会希望自己的电脑能每天定时的运行一下某个脚本,但定时执行php脚本这种概念似乎多半是在linux中才提到,下面这篇文章主要和大家分享一下在win7下如何设置计划任务,以实现定时 ...

  2. Oracle数据库基础--存储过程和函数

    一.存储过程和函数 存储过程: 对一个模块的封装 函数: 功能与存储过程几乎一样 区别: 函数必须通过return 关键字返回一个值 存储过程: 不需要return返回值 参数: 输入型参数 输出型参 ...

  3. Redis shell

    Redis shell 命令 参数 功能 redis-cli -r 将一个命令执行多次 -i 每隔几秒执行一次 -x 和|一起接收前面地输出,并执行命令 -c   -a   --scan/--patt ...

  4. stm32.cube介绍

    stm32.cube(一)——系统架构及目录结构 stm32.cube(二)——HAL结构及初始化 stm32.cube(三)——HAL.GPIO stm32.cube(四)——HAL.ADC stm ...

  5. M1卡的工作原理【转】

    本文转载自:https://blog.csdn.net/zmq5411/article/details/52042457 M1卡的工作原理 本篇对M1卡的编程是利用上述第二种方法.M1卡最为重要的优点 ...

  6. oracle-数据库的各种-锁-详解

    数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性. 如果是单用户的 ...

  7. shell将字符串转换为大写变量并将小写作为变量值

    group_name='a b c d e f g' for a in $group_name; do typeset -u a ; echo "$a='$(echo $a | tr '[A ...

  8. 尚学堂xml学习笔记

    1.打开eclipse,文件-新建java project,输入文件的名字,比如输入20181112. 2.对着src右键,选择new-file,输入文件名字,比如:book.xml. 3.开始写.x ...

  9. redis实现分布式锁——核心 setx+pipe watch监控key变化-事务

    如何设计一把分布式锁 我们用 redis 来实现这把分布式的锁,redis 速度快.支持事务.可持久化的特点非常适合创建分布式锁. 分布式环境中如何消除网络延迟对锁获取的影响 锁,简单来说就是存于 r ...

  10. 团队作业第5周——测试与发布(Alpha版本)

    1.发现的bug a.同时按下和蛇前进方向相反的键和垂直方向的任意一个键贪吃蛇会死亡(比如贪吃蛇向右行走,同时按左上或左下都会game over) b.刷新的苹果会在蛇身上出现 暂时还没能力修复,以后 ...