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 ...
随机推荐
- java和js互调 webview
public class JavaAndJSActivity extends Activity implements View.OnClickListener { private EditText e ...
- ansible3
一.setup模块 ansible的setup模块主要用来收集信息,查看参数: [root@localhost ~]# ansible-doc -s setup # 查看参数,部分参数如下: filt ...
- P4298 [CTSC2008]祭祀
P4298 [CTSC2008]祭祀 传递闭包跑一遍按联通建图 $(1)$最长反链长度=最小链覆盖=n-最大匹配 $(2)$定义作为最大匹配出现在左端点的集合为$S$,作为最大匹配出现在右端点的集合为 ...
- win10系统使用clover时程序崩溃的解决
1. 工具 ---> Internet选项 2. 程序选项卡 ---> 管理加载项 3.选择ExporerWatcher Class ---> 启用 win10对于未验证的程序状态 ...
- 深入理解JVM - Java内存模型与线程 - 第十二章
Java内存模型 主内存与工作内存 Java内存模型主要目标:定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.此处的变量(Variable)与Java编程中 ...
- Elasticsearch mapping文档相似性算法
Elasticsearch allows you to configure a scoring algorithm or similarity per field. The similarityset ...
- 【HDU 4807】Lunch Time 最小费用最大流
题意 在一个有向图当中,现在每一条边带有一个容量,现在有K个人在起点,需要到终点去吃饭,询问这K个人最后一个人到达食堂的最小时间是多少 贴一篇题解:http://blog.csdn.net/u0137 ...
- codeforces 706A A. Beru-taxi(水题)
题目链接: A. Beru-taxi 题意: 问那个taxi到他的时间最短,水题; AC代码: #include <iostream> #include <cstdio> #i ...
- Qt之log数据展示模块简要实现
Log模块主要用于实时测井数据的显示和测后曲线数据的预览和打印,为更好的展示对Qt中相关知识点的应用,特以Log模块为例对其进行简要实现. 内容导图: 一.功能需求 1.界面效果图 Log模块实现曲线 ...
- 【Python】numpy 数组拼接、分割
摘自https://docs.scipy.org 1.The Basics 1.1 numpy 数组基础 NumPy’s array class is called ndarray. ndarray. ...