题意:

给出一棵树,一个人可以在树上跳,每次最多跳\(k(1 \leq k \leq 5)\)个点

定义\(f(s,t)\)为从顶点\(s\)跳到顶点\(t\)最少需要跳多少次

求\(\sum\limits_{s<t}f(s,t)\)

分析:

注意到\(k\)很小,为了方便转移,定义:

  • \(sz(u,i)\)为\(u\)的子树中与\(u\)的距离模\(k\)等于\(i\)的孩子节点的个数
  • \(d(u,i)\)为从\(u\)跳到\(sz(u,i)\)对应的节点的跳数之和

转移:

  • \(sz(u,(i+1)\, mod \, k) += sz(v, i)\),其中\(v\)是\(u\)的儿子节点
  • \(d(u,(i+1)\, mod \, k) += d(v, i), 0<i<k\)
  • \(d(u,1 \, mod \, k) += d(v,0) + sz(v, 0)\),因为到\(v\)距离为\(k\)的整数被的那些节点转移到\(u\)时会多跳一步

统计答案:

在递归到点\(u\)时,我们统计那些\(lca(s,t)=u\)的路径的贡献

这样的路径有两类:

  • \(u\)到其孩子节点的路径
  • 来自\(u\)的两个不同子树的孩子节点形成的路径

第一类答案很好计算,就是\(\sum d(u,i)\)

第二类答案时,假设枚举到\(u\)的某个子树\(v\),而且之前的子树的答案已经更新到到\(d(u,i),sz(u,i)\)里面

枚举\(i,j\)分别为\(v\)之前的子树距离\(u\)模\(k\)为\(i\)的路径,和子树\(v\)中距离\(u\)模\(k\)为\(j\)的路径

两边各选一段路拼起来,可以通过公式快速求得答案,细节不再赘述

最终时间复杂度为\(O(k^2n)\)

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std; typedef long long LL; const int maxn = 200000 + 10; vector<int> G[maxn]; int n, k, sz[maxn][5];
LL d[maxn][5], ans; void dfs(int u, int fa) {
int tsz[5];
LL td[5];
for(int v : G[u]) if(v != fa) {
dfs(v, u);
memset(tsz, 0, sizeof(tsz));
for(int i = 0; i < k; i++) tsz[(i+1)%k] += sz[v][i]; memset(td, 0, sizeof(td));
for(int i = 1; i < k; i++) td[(i+1)%k] += d[v][i];
td[1%k] += d[v][0] + sz[v][0]; for(int i = 0; i < k; i++) {
for(int j = 0; j < k; j++) {
int delta = (i+j+k-1)/k - (i>0) - (j>0);
ans += d[u][i] * tsz[j] + td[j] * sz[u][i];
if(delta) ans += (LL) delta * sz[u][i] * tsz[j];
}
} for(int i = 0; i < k; i++) { d[u][i] += td[i]; sz[u][i] += tsz[i]; }
}
for(int i = 0; i < k; i++) ans += d[u][i];
sz[u][0]++;
} int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
} dfs(1, 0); printf("%lld\n", ans); return 0;
}

CodeForces 771C Bear and Tree Jumps 树形DP的更多相关文章

  1. Codefoces 791D. Bear and Tree Jumps 树形DP

    D. Bear and Tree Jumps   A tree is an undirected connected graph without cycles. The distance betwee ...

  2. Educational Codeforces Round 67 E.Tree Painting (树形dp)

    题目链接 题意:给你一棵无根树,每次你可以选择一个点从白点变成黑点(除第一个点外别的点都要和黑点相邻),变成黑点后可以获得一个权值(白点组成连通块的大小) 问怎么使权值最大 思路:首先,一但根确定了, ...

  3. CodeForces 161D Distance in Tree【树形DP】

    <题目链接> 题目大意:一颗无向无环树,有n个顶点,求其中距离为k的点对数是多少,(u,v)与(v,u)为同一点对. #include <cstdio> #include &l ...

  4. Codeforces 791D Bear and Tree Jump(树形DP)

    题目链接 Bear and Tree Jumps 考虑树形DP.$c(i, j)$表示$i$最少加上多少后能被$j$整除. 在这里我们要算出所有$c(i, k)$的和. 其中$i$代表每个点对的距离, ...

  5. Codeforces Round #263 (Div. 2) D. Appleman and Tree(树形DP)

    题目链接 D. Appleman and Tree time limit per test :2 seconds memory limit per test: 256 megabytes input ...

  6. Codeforces 804D Expected diameter of a tree(树形DP+期望)

    [题目链接] http://codeforces.com/contest/804/problem/D [题目大意] 给你一个森林,每次询问给出u,v, 从u所在连通块中随机选出一个点与v所在连通块中随 ...

  7. codeforces 161 D. Distance in Tree(树形dp)

    题目链接:http://codeforces.com/problemset/problem/161/D 题意:给出一个树,问树上点到点的距离为k的一共有几个. 一道简单的树形dp,算是一个基础题. 设 ...

  8. Codeforces Round #551 (Div. 2) D. Serval and Rooted Tree (树形dp)

    题目链接 题意:给你一个有根树,假设有k个叶子节点,你可以给每个叶子节点编个号,要求编号不重复且在1-k以内.然后根据节点的max,minmax,minmax,min信息更新节点的值,要求根节点的值最 ...

  9. [CF791D]Bear and Tree Jumps

    题目描述 A tree is an undirected connected graph without cycles. The distance between two vertices is th ...

随机推荐

  1. 将caj转换成pdf

    1.工具准备 电脑一台 CAJViewer 7.2 foxit pdf reader [主是要拥有一个pdf的虚拟打印机,你也可以安装其他的可以取的pdf虚拟打印机的软件.] 2.步骤 (1)用CAJ ...

  2. PHP:将json数据放进html标签中的详细讲解

    1.在controller中调用某方法,得到最终的json数据.根据框架开发形式,将Json数据传入视图中 2.在视图中,我们放置一个hidden形式的标签,并获取到json数据 3.这时候,我们查看 ...

  3. java——栈和队列 面试题

    (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min()的栈,要求min.push.pop.的时间复杂度都是O(1) (6)判断栈的push ...

  4. POJ - 3109 Inner Vertices

    不存在-1的情况,而且最多一轮就结束了.如果新增加的黑点v0会产生新的黑点v1,那么v0和v1肯定是在一条轴上的,而原来这条轴上已经有黑点了. 离散以后扫描线统计,往线段上插点,然后查询区间上点数. ...

  5. centos6 yum 安装 install c++4.8 gcc4.8

    cd /etc/yum.repos.d wget http://people.centos.org/tru/devtools-1.1/devtools-1.1.repo yum --enablerep ...

  6. 通过WEB网管登录

    6.1  通过WEB网管登录简介 S5100-SI/EI系列以太网交换机提供内置的WEB Server,用户可以通过WEB网管终端(PC)登录到交换机上,利用内置的WEB Server以WEB方式直观 ...

  7. webpack-dev-middleware插件的使用

    我们在使用webpack 编译文件时,每次改动文件都要去重新编译,是不是很麻烦,这时候我们就用到了webpack-dev-middleware 插件,该插件对更改的文件进行监控,编译, 一般和 web ...

  8. MCV 的几种表单提交方式

    一,MVC  HtmlHelper方法 Html.BeginForm(actionName,controllerName,method,htmlAttributes){}   其中actionName ...

  9. 多重网格方法(Multigridmethod)

    原文链接 多重网格方法是解微分方程的方法.这个方法的好处是在利用迭代法收敛结果的时候速度特别快.并且,不管是否对称,是否线性都无所谓.它的值要思想是在粗糙结果和精细结果之间插值. 前面介绍了Gauss ...

  10. 数据库MySQL基本介绍安装使用及文件导入导出

    1.数据库(data base) 1.1 简述 把文件存储在一台电脑上(服务器),其他电脑用户可以通过账号密码登陆,通过网络去访问这台电脑上的文件,但是由于每个人的数据是不同的,所以你只能通过自己的账 ...