题干:

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

给定一棵N的节点的树,节点编号1~N,并且1号节点是根节点。

小Hi会反复询问小Ho一个问题:给定两个节点a和b,有多少对节点c和d满足c < d且c到d的路径包含完整的a到b的路径?

你能帮帮小Ho吗?

输入

第一行包含两个数N和M,依次是节点总数和问题总数。

第2~N行每行包含两个整数u和v,代表u是v的父节点。

以下M行每行包含两个整数a和b,代表一个问题。

对于30%的数据,1 ≤ N, M ≤ 1000

对于100%的数据,1 ≤ N, M ≤ 100000

输出

对于每个问题输出一个整数,代表答案。

样例输入

7 2
1 2
1 3
2 4
2 5
3 6
3 7
2 3
2 4

样例输出

9
6

解题报告:

跑半遍LCA,到他俩深度相同的时候停止。然后判断是否在同一条链上,分别返回不同的答案就行了。注意在同一条链的时候,不能用u和v的,需要用u(深度大的)的和对应链上dep[v]+1的那个点的。(来看几发错误代码)

错误代码1:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
ll a[MAX];
int fa[MAX][33],dep[MAX],sum[MAX];
int n,m;
vector<int> vv[MAX];
void dfs(int cur,int rt) {dep[cur] = dep[rt]+1;sum[cur] = 1;for(int i = 1; i<=31; i++) {fa[cur][i] = fa[fa[cur][i-1]][i-1];}int sz = vv[cur].size();for(int i = 0; i<sz; i++) {int v = vv[cur][i];if(v == rt) continue;dfs(v,cur);sum[cur] += sum[v];}
}
int lca(int u,int v) {if(dep[u] < dep[v]) swap(u,v);ll ans1 = 1LL*sum[u] * (n - sum[v] + (sum[v]-sum[u]));ll ans2 = 1LL*sum[u] * sum[v];int dc = dep[u] - dep[v];for(int i = 0; i<=31; i++) {if(dc>>i & 1) u = fa[u][i];}if(u == v) {return ans1;}else return ans2;for(int i = 31; i>=0 && u != v ; i--) {if(fa[u][i] != fa[v][i]) {u = fa[u][i];v = fa[v][i];}}int res = fa[u][0];//u和v的最近公共祖先.}
int main()
{cin>>n>>m;for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);fa[v][0] = u;vv[u].pb(v);vv[v].pb(u);}dfs(1,0);while(m--) {int u,v;cin>>u>>v;cout << lca(u,v) <<endl;}return 0 ;}

错误代码2:

ll lca(int u,int v) {if(dep[u] < dep[v]) swap(u,v);//ll ans1 = (n - sum[v] + (sum[v]-sum[u]));ll sumu = sum[u] ,sumv = sum[v];int dc = dep[u] - dep[v];for(int i = 31; i>=0; i--) {//if(dc>>i & 1) u = fa[u][i];if(dep[u]-1 != dep[v]) {u = fa[u][i];} }if(fa[u][0] == v) {//说明在一条链上 return sumu*(n-sum[u]);}else return sumu*sumv;for(int i = 31; i>=0 && u != v ; i--) {if(fa[u][i] != fa[v][i]) {u = fa[u][i];v = fa[v][i];}}int res = fa[u][0];//u和v的最近公共祖先.
}

错误代码3:

ll lca(int u,int v) {if(dep[u] < dep[v]) swap(u,v);//ll ans1 = (n - sum[v] + (sum[v]-sum[u]));ll sumu = sum[u] ,sumv = sum[v];int dc = dep[u] - dep[v];for(int i = 31; i>=0; i--) {//if(dc>>i & 1) u = fa[u][i];if(dep[u] < dep[v]) {u = fa[u][i];} }if(fa[u][0] == v) {//说明在一条链上 return sumu*(n-sum[u]);}else return sumu*sumv;for(int i = 31; i>=0 && u != v ; i--) {if(fa[u][i] != fa[v][i]) {u = fa[u][i];v = fa[v][i];}}int res = fa[u][0];//u和v的最近公共祖先.
}

错误代码4:

ll lca(int u,int v) {if(dep[u] < dep[v]) swap(u,v);ll sumu = sum[u] ,sumv = sum[v];for(int i = 31; i>=0 && dep[v] + 1 <= dep[u]; i--) {if(dep[fa[u][i]] < dep[v]) {u = fa[u][i];} }if(fa[u][0] == v) {//说明在一条链上 return sumu*(n-sum[u]);}else return sumu*sumv;
}

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
ll a[MAX];
int fa[MAX][33],dep[MAX],sum[MAX];
int n,m;
vector<int> vv[MAX];
void dfs(int cur,int rt) {dep[cur] = dep[rt]+1;sum[cur] = 1;for(int i = 1; i<=31; i++) {fa[cur][i] = fa[fa[cur][i-1]][i-1];}int sz = vv[cur].size();for(int i = 0; i<sz; i++) {int v = vv[cur][i];if(v == rt) continue;dfs(v,cur);sum[cur] += sum[v];}
}
ll lca(int u,int v) {if(dep[u] < dep[v]) swap(u,v);ll sumu = sum[u] ,sumv = sum[v];for(int i = 31; i>=0 && dep[v] + 1 <= dep[u]; i--) {if(dep[fa[u][i]] < dep[v]) {u = fa[u][i];} }if(fa[u][0] == v) {//说明在一条链上 return sumu*(n-sum[u]);}else return sumu*sumv;
}
int main()
{cin>>n>>m;for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);fa[v][0] = u;vv[u].pb(v);vv[v].pb(u);}dfs(1,0);while(m--) {int u,v;scanf("%d%d",&u,&v);//cin>>u>>v;cout << lca(u,v) <<endl;}return 0 ;}

总结:

另外注意一下,,,对于一棵树,dep值大的是在下面啊(远离根),别想反了。

【hihocoder - offer编程练习赛60 C】路径包含问题(LCA,树上倍增)相关推荐

  1. 【hihocoder - offer编程练习赛60 B】最大顺子(双指针,思维)

    题干: 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 你有N张卡片,每张卡片上写着一个正整数Ai,并且N张卡片上的整数各不相同. 此外,你还有M张百搭卡片,可以当作写着 ...

  2. 【hihocoder - offer编程练习赛60 A】hohahola(贪心,二分)

    题干: 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 有一种叫作hohahola的饮料,售价是X元一瓶.小Hi非常喜欢这种饮料,但是他现在身无分文. 不过小Hi有N张优 ...

  3. 【Hihocoder - offer编程练习赛86 - C】跳数游戏(STLset或map预处理,dp)

    题干: 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个长度为N的数组A1, A2, ... AN,请你判断其中有几个元素Ai按如下跳跃规则能跳到最后一个元素AN ...

  4. 【Hihocoder - offer编程练习赛39 - D】前缀后缀查询(后缀字典树,哈希,思维)

    题干: 时间限制:10000ms 单点时限:1000ms 内存限制:512MB 描述 给定一个包含N个单词的字典:{W1, W2, W3, ... WN},其中第i个单词Wi有具有一个权值Vi. 现在 ...

  5. *【Hihocoder - offer编程练习赛94 - A】最短管道距离(中位数)

    题干: 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在一张2D地图上有N座城市,坐标依次是(X1, Y1), (X2, Y2), ... (XN, YN). 现在H国 ...

  6. 【Hihocoder - offer编程练习赛93 套题题解】交错01串(贪心,暴力)方格矩阵高度(模拟)数对(STLmultiset)修整土地(网络流)

    A: 题干: 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi要将一个01串S传输给小Ho,由于S非常长,所以小Hi决定用长度为N的2个数组A = [A1, A2, ...

  7. 最简真分数c语言,HihoCoder1655 : 第K小最简真分数([Offer收割]编程练习赛39)(唯一分解+容斥定理+二分)(不错的数学题)...

    描述 给一个整数N,请你求出以N为分母的最简(既约)真分数中第K小的是多少? 输入 两个整数N个K. 对于30%的数据,1 <= N <= 1000000 对于100%的数据,1 < ...

  8. 剑指offer编程题(JAVA实现)——第38题:二叉树的深度

    github https://github.com/JasonZhangCauc/JZOffer 剑指offer编程题(JAVA实现)--第38题:二叉树的深度 题目描述 输入一棵二叉树,求该树的深度 ...

  9. LeetCode-剑指 Offer 12. 矩阵中的路径

    剑指 Offer 12. 矩阵中的路径 思路一:DFS+回溯 DFS 解析: 递归参数: 当前元素在矩阵 board 中的行列索引 i 和 j ,当前目标字符在 word 中的索引 k . 终止条件: ...

最新文章

  1. Oculus也陷隐私门:向Facebook发送隐私数据
  2. 皮一皮:论北方有多冷...
  3. Perl一行式:文本编解码、替换
  4. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1112:最大值和最小值的差
  5. Python进阶06 循环对象
  6. duckduckgo 国内_DuckDuckGo的Instant Answers项目的7课
  7. OpenShift 4 - DevSecOps (2) - 修复 RHACS 发现的安全隐患
  8. PostgreSQL rocks, except when it blocks: Understanding locks
  9. python的for循环语句range_Python入门第7课,循环结构学习,for语句range函数的3种用法...
  10. Android-SDK下载及安装配置教程
  11. 前端用户体验提升系列(一)最常见的用户体验指标和提升方式
  12. 最强PostMan使用教程(1)
  13. Python 并发编程
  14. 自动取款机 冲正交易
  15. 豆沙绿护眼色样式在html中的代码
  16. czl蒻蒟的OI之路7
  17. PC端如何下载B站里面的视频?
  18. 友价T5商城系统一键生成SiteMap网站地图插件【chajian_sitemap_builder.php】
  19. CodeLite工具的使用
  20. 小学计算机室每日管理日志,2017小学信息技术工作研修日志

热门文章

  1. 关于html和javascript在浏览器中的加载顺序问题的讨论(zz)
  2. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第21篇]CRT算法如何提高RSA的性能?
  3. [剑指offer][JAVA]面试题第[04]题[二维数中的查找][数组]
  4. python第三方库全部_自动更新Python所有第三方库
  5. 创建实现一个简单的web项目
  6. php中介者,PHP设计模式 - 中介者模式
  7. rdd分片 spark_Spark分区
  8. php中一级标题和二级标题,什么是一级标题,一二三标题格式举例
  9. java 6大原则_java 6大设计原则 一:观察者模式
  10. java删除集合元素吗_java如何删除集合中的元素