P3565 [POI2014]HOT-Hotels

参考题解

题目大意:
给定一棵树,在树上选 3 个点,要求两两距离相等,求方案数。

三个点树上两两距离为d存在下面两种情况

  • 某个点三个子树(保证该点是LCA)中分别由三个点距离它为d
  • 对于某一个点,它的 d 级祖先以及子树内两个以它为LCA,距它 d 的点

对于情况一,设计dp: fu,jf_{u,j}fu,j​表示以uuu为根的子树,距i距离为jjj的点数

对于情况二,设计dp:gu,jg_{u,j}gu,j​表示以uuu为根的子树,两个点的到LCA距离相等(此出用d表示),LCA到uuu的距离为d−jd-jd−j的点对

对于fu,jf_{u,j}fu,j​的状态转移十分显然:fu,j=∑v∈sonufv,j−1f_{u,j}=\sum_{v\in son_u }f_{v,j-1}fu,j​=∑v∈sonu​​fv,j−1​

而对于gu,jg_{u,j}gu,j​来说存在两种情况

  • 某个子树内部存在两个点:gu,j=∑v∈sonugv,j+1g_{u,j}=\sum_{v\in son_u}g_{v,j+1}gu,j​=∑v∈sonu​​gv,j+1​
  • 两个不同的子树各贡献一个点,以uuu为LCA:gu,j=∑v,w∈sonu,v≠wfv,j−1×fw,j−1g_{u,j}=\sum_{v,w\in son_u,v \ne w} f_{v,j-1}×f_{w,j-1}gu,j​=∑v,w∈sonu​,v​=w​fv,j−1​×fw,j−1​

很明显,第二中情况fv,j−1×fw,j−1,fw,j−1×fv,j−1f_{v,j-1}×f_{w,j-1}, f_{w,j-1}×f_{v,j-1}fv,j−1​×fw,j−1​,fw,j−1​×fv,j−1​是同一种情况,这里我们让vvv是uuu较靠前的儿子即可避免重复计算

而对于答案计算来说也存在两种情况:
首先对于三个点树上两两距离为d的情况都可以看成两个点在一个子树中,而另一个点“别处

  • 在子树vvv中选一个点,而在其他子树中选两个点:gu,j+1×fv,jg_{u,j+1}×f_{v,j}gu,j+1​×fv,j​
  • 在子树vvv中选两个点,而在其他子树中选一个点:fu,j−1×gv,jf_{u,j-1}×g_{v,j}fu,j−1​×gv,j​

同样为了避免重复计算只需要让其他子树搞成vvv前面的子树即可
注意上述gu,j+1g_{u,j+1}gu,j+1​和fu,j−1f_{u,j-1}fu,j−1​都还未算vvv对其的贡献,这个只需要先计算答案在加贡献即可。

计算状态数组和答案时,都有计算前面子树的情况,直接运用前缀和的思想即可边计算答案,边转移数组。

这里要提一点,我们至今没有提到gu,0g_{u,0}gu,0​对答案的贡献,它确实对答案有贡献,但是我们已经计算过了,如果在此加上会重复计算。

而其他博主在计算的时候加上gu,0g_{u,0}gu,0​实际上增加的时gwson,1g_{wson,1}gwson,1​即重儿子的贡献。

根据g的转移方程可知道:gu,0g_{u,0}gu,0​的贡献全部来自于∑v∈sonugv,1\sum_{v\in son_u}g_{v,1}∑v∈sonu​​gv,1​,而计算fu,j−1×gv,jf_{u,j-1}×g_{v,j}fu,j−1​×gv,j​对答案的贡献时我们具体写一下fu,0×gv,1f_{u,0}×g_{v,1}fu,0​×gv,1​而fu,0=1f_{u,0}=1fu,0​=1,因此已经计算过gu,0g_{u,0}gu,0​的贡献!!!


然后就是长链剖分优化dp,每次保存长儿子的贡献,其他儿子暴力合并,每条长链都会在链头暴力合并一次时间复杂度O(len)O(len)O(len)总的合并时间复杂度O(n)O(n)O(n)

最后如果写指针版本的话,由于g数组是倒着转移的,fff要多开一倍的内存,否则g可能倒回来覆盖掉fff

code

#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
constexpr int N=5010;
int h[N],e[2*N],ne[2*N],idx;
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int n;
int dep[N],son[N];
void dfs1(int u,int fa)
{for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs1(v,u);if(dep[v]>dep[son[u]]) son[u]=v;}dep[u]=dep[son[u]]+1;
}ll pool[4*N];
ll *f[N],*g[N],*now=pool;
ll ans;
void dfs2(int u,int fa)
{f[u][0]=1;if(son[u]){f[son[u]]=f[u]+1;g[son[u]]=g[u]-1;dfs2(son[u],u);ans+=g[son[u]][1];// 加上重儿子的贡献}for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa||v==son[u]) continue;f[v]=now;now+=dep[v]<<1;g[v]=now;now+=dep[v];dfs2(v,u);// 边计算for(int j=0;j<dep[v];j++){if(j) ans+=f[u][j-1]*g[v][j];ans+=g[u][j+1]*f[v][j];}// 边转移for(int j=0;j<dep[v];j++){g[u][j+1]+=f[u][j+1]*f[v][j];if(j) g[u][j-1]+=g[v][j];f[u][j+1]+=f[v][j];}}}
int main()
{IO;cin>>n;memset(h,-1,sizeof h);for(int i=1;i<n;i++){int u,v;cin>>u>>v;add(u,v);add(v,u);}dfs1(1,0);f[1]=now;now+=dep[1]<<1;//多开一倍的内存g[1]=now;now+=dep[1];dfs2(1,0);cout<<ans<<'\n';return 0;
}

菜菜的我搞了一天这个题啊啊啊啊

P3565 [POI2014]HOT-Hotels(树形dp+长链剖分)相关推荐

  1. 【BZOJ4543】【POI2014】Hotel加强版(长链剖分)

    传送门 题意:求树上满足三点之间距离两两相等的三元组个数 n≤1e5n\le 1e5n≤1e5 原题数据是n≤5000n\le5000n≤5000 考虑怎么做 f[u][i]f[u][i]f[u][i ...

  2. HDU - 5242 Game(树形dp+树链剖分/树上贪心+思维)

    题目链接:点击查看 题目大意:给出一棵包含n个节点的树,每个节点都有一个权值,整棵树的根是点1,问从点1开始向下一直走到叶子节点,可以走k次,怎么样走权值和最大,每个节点被走过一次后权值会变为0 题目 ...

  3. 长链剖分优化树形dp

    apio铁牌告辞(开场想打暴力然后gedit码代码5个小时没写完三题最低档暴力真是快乐),听课也就学到了一丢丢这个东西. 模板题: https://www.luogu.org/problemnew/s ...

  4. 【BZOJ4543】Hotel加强版【神仙树形dp】【长链剖分】

    题意:给一棵 nnn 个点的树,求两两距离相等的三元组个数. n≤105n\leq 10^5n≤105 显然相当于是找一个点到这三个点距离相等.子树内和子树外到当前点的距离为某个值的点的个数可以长链剖 ...

  5. 【BZOJ】4543: [POI2014]Hotel加强版-长链剖分DP

    传送门:bzoj4543 题解 三点两两距离相等的情况如下图: 设 f [ i ] [ j ] f[i][j] f[i][j]表示 i i i子树中与 i i i距离为 j j j(相对深度为 j j ...

  6. 中心城镇问题(长链剖分优化树形dp)

    problem 给定 nnn 个城市,n−1n-1n−1 条道路,形成一棵树.每座城市上的人口为 wiw_iwi​. 现要修建若干个中心城镇,满足任意两个中心城镇之间的距离严格大于 kkk. 最大化中 ...

  7. BZOJ4543/BZOJ3522 [POI2014]Hotel加强版(长链剖分)

    题目好神仙--这个叫长链剖分的玩意儿更神仙-- 考虑dp,设\(f[i][j]\)表示以\(i\)为根的子树中到\(i\)的距离为\(j\)的点的个数,\(g[i][j]\)表示\(i\)的子树中有\ ...

  8. 【十二省联考2019】希望【点边容斥】【换根dp】【长链剖分】【线性数据结构】【回退数据结构】【离线逆元】

    题意:给一棵树,两个参数 k,Lk,Lk,L,需要选择 kkk 个连通块,使得这 kkk 个连通块存在一个公共点,且该公共点到 kkk 个连通块内的任意一点的距离不超过 LLL,求方案数 模 9982 ...

  9. 【CF1009F】 Dominant Indices (长链剖分+DP)

    题目链接 \(O(n^2)\)的\(DP\)很容易想,\(f[u][i]\)表示在\(u\)的子树中距离\(u\)为\(i\)的点的个数,则\(f[u][i]=\sum f[v][i-1]\) 长链剖 ...

最新文章

  1. c2054未定义基类_c++ - 错误C2504:基类未定义 - 堆栈内存溢出
  2. LNMP Nginx 499 问题 第三方回调异常
  3. 几道偏序问题(数据结构)
  4. 数据库有哪些分类?应该怎样选择?终于有人讲明白了
  5. 使用Apache HttpComponents访问https接口(及老版本DefaultHttpClient deprecated)
  6. python读取json数据教程_Python教程之解析json数据
  7. linux删除文件未释放空间问题处理
  8. 路由跟踪之tcptraceroute IP延时之tcpping
  9. 卫星定位领域相关基础知识汇总
  10. 俄勒冈之旅_俄勒冈州立大学开源实验室主持160个项目
  11. iCaRL: Incremental Classifier and Representation Learning
  12. C#:控制台数绵羊小程序
  13. 【SAP ABAP学习资料】(财务相关)BTE增强查找,新增
  14. 大家一起来玩游戏-24点(递归)
  15. 服务器麒麟系统是arm还是x64,麒麟arm环境安装ceph
  16. 如何用python计算函数的值域_(Max第一篇)Python基础代数运算大全
  17. 加密数据储存工具:Keychain 介绍与使用
  18. PTA 计算年龄问题 (30 分)
  19. 【转】YV12 and NV12
  20. HDU 2033 - 人见人爱 A + B

热门文章

  1. php 谷歌语音,php 语音参考
  2. linux编程两个子进程,Linux中fork同时创建多个子进程的方法
  3. java地图 热力图,腾讯地图数据可视化之热力图
  4. leedcode04:转换字符串的最少操作次数
  5. 7-3 树的同构 (25 分)(思路加详解)来呀baby!!!!!!!!
  6. 每天一小时python官方文档学习(四)————数据结构之列表
  7. android system window,Android之属性fitsSystemWindows
  8. 异步清零和同步置数/清零的区别
  9. [蓝桥杯2015决赛]胡同门牌号-模拟+枚举
  10. P4900 食堂(数学式子推导)