题目链接: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. linux下安装https证书

    https://www.aliyun.com/jiaocheng/165422.html

  2. EASYARM-IMX283 烧写uboot和linux系统

    新入手一台EASYARM-IMX283开发板(以下简称IMX823),价格比较便宜,配置也不错. 开发板默认安装了WINCE,我还是决定重新烧写uboot和linux内核. 开发板配套光盘里面有不少烧 ...

  3. Linux(Ubuntu16.04)+GitLab8.17deb安装包搭建Git仓库(代码管理系统)

    1 下载GitLab安装包 2  执行安装命令 3 验证是否安装和启动成功 4 修改管理员密码 5 其它说明 5.1修改访问URL 5.2修改邮件配置 5.3修改web端口 1下载GitLab安装包 ...

  4. 7th

    2017-2018-2 20179212<网络攻防技术>第7周作业 课本学习 Windows操作系统基本框架 1.windows基本结构分为运行于处理器特权模式的操作系统内核以及运行在处理 ...

  5. mysql客户首末单时间 group by用法_20160927

    一.取用户第一次下单时间 SELECT city,username,`order_date` AS 首单日期,金额 AS 首单金额 FROM ( SELECT city,username,`order ...

  6. P1955 [NOI2015]程序自动分析[离散化+并查集]

    大水题一道,不明白为什么你谷评了个蓝.一看就是离散化,先去满足相等的条件,相等即为两点联通,或者说在同一个集合内.再看不相等,只有两元素在同一集合才不满足.裸的disjoint-set直接上,常数巨大 ...

  7. 「LuoguP3389」【模板】高斯消元法

    题目背景 Gauss消元 题目描述 给定一个线性方程组,对其求解 输入输出格式 输入格式: 第一行,一个正整数 nn 第二至 n+1n+1行,每行 n+1n+1 个整数,为a_1, a_2 \cdot ...

  8. Java网络与多线程系列之1:实现一个简单的对象池

    前言 为什么要从对象池开始呢,先从一个网络IO操作的demo说起 比如下面这段代码,显而易见已经在代码中使用了一个固定大小的线程池,所以现在的重点在实现Runnble接口的匿名对象上,这个对象每次创建 ...

  9. 洛谷【P4883】mzf的考验

    浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html 浅谈\(fhq\)_\(treap\):https://www.cnblogs.com ...

  10. CF285 E Positions in Permutations——“恰好->大于”的容斥和允许“随意放”的dp

    题目:http://codeforces.com/contest/285/problem/E 是2018.7.31的一场考试的题,当时没做出来. 题解:http://www.cnblogs.com/y ...