719D(树形dp)
题目链接: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)的更多相关文章
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
随机推荐
- PHP通过session id 实现session共享和登录验证的代码
先说说,这个机制的用途吧,到现在为止战地知道这个机制有两个方面的用途: 首先,多服务器共享session问题,这个大家应该都能够理解的,当一个网站的用户量过大,就会使用服务器集群,例如专门有一个登录用 ...
- php微信支付测试开发(流程已通)
必要条件: appid //公众号后台开发者中心获得(和邮件内的一样) mchid//邮件内获得 key//商户后台自己设置 appsecret //公众号开发者中心获得 两个证书文件,邮件内 ...
- Java for LeetCode 107 Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...
- NiFi汉化
①在源文件中的 source-nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src中修 ...
- mini2440 u-boot下设置tftp
在烧写好u-boot后,重新启动mini2440,一直按空格键进入u-boot界面: U-Boot 月 - ::) modified by tekkamanninja (tekkamanninja@. ...
- struts + hibernate笔记
1.hibernate: 1) Restrictions.eq 判断是否相等== (场景:一个类A中的属性t,这个属性t是另一个类B中的ID,找出输入为这个属性t的所有类A) tasks = ses ...
- POJ3450 Corporate Identity —— 后缀数组 最长公共子序列
题目链接:https://vjudge.net/problem/POJ-3450 Corporate Identity Time Limit: 3000MS Memory Limit: 65536 ...
- HDU 4405 Aeroplane chess:期望dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4405 题意: 你在下简化版飞行棋... 棋盘为一个线段,长度为n. 上面有m对传送门,可以直接将你从a ...
- Linus Torvalds: 成功的项目源于99%的汗水与1%的创新
2017年2月15日,在加利福尼亚州的开源领袖峰会上,由Linux基金会执行董事Jim Zemlin进行的一次采访中,Torvalds讨论了他如何管理Linux内核的开发以及他对工作的态度. Linu ...
- IOC/DI控制反转与依赖注入
IOC/DI控制反转与依赖注入 IOC和DI表现的效果的是一样的只不过对于作用的对象不同,有了不一样的名字. 先用一个现实的例子来说明IOC/DI表现出来的效果.