题目描述

有一棵n个点的树和两个整数p, q,求满足以下条件的四元组(a, b, c, d)的个数:
  1.$1\leq a,b,c,d \leq n$
  2.点a到点b的经过的边数为p。
  3.点c到点d的经过的边数为q。
  4.不存在一个点,它既在点a到点b的路径上,又在点c到点d的路径上。

输入描述

第一行三个整数n,p,q。
  接下来n - 1行,每行两个整数u, v,表示树上存在一个连接点u和点v的边。

输出描述

输出一个整数,表示答案。
  示例1
  输入
  5 2 1
  1 2
  2 3
  3 4
  2 5
输出
  4
说明
  合法的四元组一共有:
  (1, 5, 3, 4),
  (1, 5, 4, 3),
  (5, 1, 3 ,4),
  (5, 1, 4, 3)。
示例2
  输入
  4 1 1
  1 2
  2 3
  3 4
输出
  8
备注:
  对于前20%的数据,n,p,q≤50。
  对于前40%的数据,n,p,q≤200。
  对于另外10%的数据,p = 2, q = 2。
  对于另外10%的数据,树是一条链。
  对于另外10%的数据,树随机生成。
  对于所有数据1≤n,p,q≤3000,1≤u,v≤n,保证给出的是一棵合法的树。

分析

我已经弱到连$n^2$枚举路径都不会了

再一次求助Master_Yi

这个题只要理顺了就挺好想的了(说得好像我想得出来似的。

由于不相交的情况不好求,所直接看相交的情况。

找规律可以发现,如果两条路径相交,其中必有一条路径两个端点的lca在另一条路径上

所有可以枚举长度为p的路径,减去在以这条路径上的点为端点lca的长度为q的路径

然后又枚举长度为q的路径,减去在以这条路径上的点为端点lca的长度为p的路径

发现当路径端点lca相同的情况被多算了一次,于是就加回来

那么如何实现呢?

设sq[x],sp[x]分别表示以x为端点lca,长度为q和长度为p的路径条数

枚举路径是$n^2$的,如果不能优化的话,那么我们现在需要的是快速求出一条路径上的sq或sp和

现在要求的是一条路径的和,一个一个找点肯定会T,所以可以预处理一些东西能让我们能够拼凑出答案

如果预处理从根到某个节点x上的路径的sq之和与sp之和,记为ssq[x]与spp[x]

那么以i,j为两端点的路径中sq和sp之和就为ssq[i]+ssq[j]-ssq[lca[i][j]]-ssq[fa[lca[i][j]]]与ssp[i]+ssp[j]-ssp[lca[i][j]]-ssp[fa[lca[i][j]]]

感觉有些与前缀和类似。。。。。。

这样就可以O(1)计算了,总的时间复杂度就为O(n^2)

跟Master_Yi几乎一样的Code

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
int fa[maxn],dep[maxn],ori[maxn],f[maxn][maxn],lca[maxn][maxn];
int n,p,q,ecnt,Sp,Sq,v[maxn<<],nx[maxn<<],sq[maxn],sp[maxn],vis[maxn],info[maxn];
int find(int x){return !ori[x]?x:ori[x]=find(ori[x]);}
void add(int u1,int v1){nx[++ecnt]=info[u1];info[u1]=ecnt;v[ecnt]=v1;}
void dfs1(int x,int fa)
{
f[x][]=;vis[x]=;for(int i=;i<=n;i++)if(vis[i])lca[x][i]=lca[i][x]=find(i);
for(int e=info[x];e;e=nx[e])if(v[e]!=fa)
{
dfs1(v[e],x);
for(int i=;i<q;i++)sq[x]+=f[x][i]*f[v[e]][q-i-];
for(int i=;i<p;i++)sp[x]+=f[x][i]*f[v[e]][p-i-];
for(int i=;i<max(p,q);i++)f[x][i+]+=f[v[e]][i];
}
ori[x]=fa;Sq+=sq[x];Sp+=sp[x];
}
void dfs2(int x,int f){sq[x]+=sq[f];sp[x]+=sp[f];dep[x]=dep[fa[x]=f]+;for(int e=info[x];e;e=nx[e])if(v[e]!=f)dfs2(v[e],x);}
int main()
{
scanf("%d%d%d",&n,&p,&q);
for(int i=,u1,v1;i<n;i++)scanf("%d%d",&u1,&v1),add(u1,v1),add(v1,u1);
dfs1(,);dfs2(,);long long ans=p!=q?1ll*Sp*Sq:1ll*Sp*(Sq-)/;
for(int i=;i<=n;i++)for(int j=i+;j<=n;j++)
{
int len=dep[i]+dep[j]-*dep[lca[i][j]];
if(len==p&&len==q){ans-=sq[i]+sq[j]-sq[lca[i][j]]-sq[fa[lca[i][j]]]-;continue;}
if(len==p)ans-=sq[i]+sq[j]-sq[lca[i][j]]-sq[fa[lca[i][j]]];
if(len==q)ans-=sp[i]+sp[j]-sp[lca[i][j]]-sp[fa[lca[i][j]]];
}
for(int i=;i<=n;i++)
if(p==q)ans+=1ll*(sp[i]-sp[fa[i]])*(sq[i]-sq[fa[i]]-)/;
else ans+=1ll*(sp[i]-sp[fa[i]])*(sq[i]-sq[fa[i]]);
printf("%lld\n",p==q?ans<<:ans<<);
}

【牛客】路径计数机 (树形dp 前缀和)的更多相关文章

  1. 牛客练习赛55 E-树 树形DP

    题意 你有一颗大小为\(n\)的树,点从\(1\)到\(n\)标号. 设\(dis⁡(x,y)\)表示\(x\)到\(y\)的距离. 求\(\sum_{i=1}^{n}\sum_{j=1}^{n}di ...

  2. 牛客网华为机试题之Python解法

    牛客网华为机试题之Python解法 第1题 字符串最后一个单词的长度 a = input().split(" ") print(len(a[-1])) 第2题 计算字符个数 a = ...

  3. [BZOJ 1907] 树的路径覆盖 【树形DP】

    题目链接:BZOJ - 1907 题目分析 使用树形 DP,f[x][0] 表示以 x 为根的子树不能与 x 的父亲连接的最小路径数(即 x 是一个折线的拐点). f[x][1] 表示以 x 为根的子 ...

  4. bzoj 2111: [ZJOI2010]Perm 排列计数【树形dp+lucas】

    是我想复杂了 首先发现大于关系构成了一棵二叉树的结构,于是树形dp 设f[i]为i点的方案数,si[i]为i点的子树大小,递推式是\( f[i]=f[i*2]*f[i*2+1]*C_{si[i]-1} ...

  5. UOJ#290. 【ZJOI2017】仙人掌 仙人掌,Tarjan,计数,动态规划,树形dp,递推

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ290.html 题解 真是一道好题! 首先,如果不是仙人掌直接输出 0 . 否则,显然先把环上的边删光. ...

  6. 牛客练习赛35-背单词-线性DP

    背单词 思路 :dp[ i ]  [ 0 ]表示 第i 位放的元音  dp[ i ]  [ 1 ]表示 第i 位放的辅音 ,cnt [ i ]含义是 长度为 i 的方案数. 转移  :dp[ i ]  ...

  7. 计蒜客 Red Black Tree(树形DP)

    You are given a rooted tree with n nodes. The nodes are numbered 1..n. The root is node 1, and m of ...

  8. bzoj1907: 树的路径覆盖(树形DP)

    一眼题... f[i][0]表示在i连接一个子树的最小值,f[i][1]表示在i连接两个子树的最小值,随便转移... 样例挺强的1A了美滋滋... UPD:学习了2314的写法之后短了好多T T #i ...

  9. BZOJ_2111_[ZJOI2010]Perm 排列计数_树形DP+组合数学

    Description 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic ...

随机推荐

  1. English--定语从句

    English|定语从句 从介绍从句开始,英语的句子已经开始逐渐复杂了!做好心理准备,三大从句介绍完毕,会介绍分词短语.废话不多说,直接开始干! 前言 目前所有的文章思想格式都是:知识+情感. 知识: ...

  2. 【开发笔记】-MySQL数据库5.7+版本,编码格式设置

    原因 昨天不小心把数据库搞崩了,重装了5.7.27版本得mysql数据库,在安装过程中并没有设置数据库默认编码格式等操作.在把项目启动后,jpa自动创建表结构,会把数据库,表,字段的编码自动设置为IS ...

  3. spring boot 的request.getServletContext().getRealPath路径获取问题

    默认情况下springboot中request.getServletContext().getRealPath 返回的是一个临时文件夹的地址 通过查看源代码 位置在 org.springframewo ...

  4. SDk编程基础

    一.Android简介: 由Andy Rubin开发, 常用手机版本:谷哥:Nexus.华为:EMUI.魅族:Flyme Adnroid是运行在Java虚拟机(JVM)上大部分免费的开源的.应用通过权 ...

  5. Python如何去实际提高工作的效率?也许这个会有用!

    4月初,班主任的某次周会议上,华华关切的问了一下:最近班主任们有什么难题吗?就是花费了你们大部分时间的工作!我们Python天团可以帮你们解决问题. 班主任大主管星星说:有.目前有一个大难题.我们每天 ...

  6. python实现广度优先搜索

    from collections import deque #解决从你的人际关系网中找到芒果销售商的问题#使用字典表示映射关系graph = {} graph["you"] = [ ...

  7. 响应式js库——rxjs

    原文地址:https://rxjs.dev/guide/overview 简介 RxJS 是组合异步以及基于事件的使用可观察者序列的程序类库.它提供一个核心类型,Observable,附属类型(Obs ...

  8. Docker 0x05: Dockerfile制作镜像

    目录 Dockerfile制作镜像 一句话什么是dockerfile dockerfile脚本指令 小结 Dockerfile制作镜像 dockerfile 可以是制作自己镜像的脚本文件,按照这个脚本 ...

  9. Sublime Text3 安装 CTags 插件出现乱码

    1.下载ctags.exe 可以直接下载我上传好的资源:http://download.csdn.net/download/zhaoxd200808501/9971251.或者网络上其他地方也可以下载 ...

  10. zabbix监控项字体乱码的处理方法

    一.新安装完的查看项目的时候字体是乱码的 二.在控制面板的字体中复制出系统的“微软雅黑”字体,粘贴到桌面 粘贴出来之后会产生两个文件,msyhbd.ttf为加粗的字体 三.修改并替换字符集 我是编译安 ...