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

题干:

时间限制: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值大的是在下面啊(远离根),别想反了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【面试题 - 最大值减去最小值小于或等于 num 的子数组数量】滑动窗口

题干&#xff1a; 解题报告&#xff1a; 我们用两个指针&#xff08;i&#xff0c;j&#xff09;分别代表窗口的左边界和右边界&#xff0c;窗口也就是子数组&#xff1b; 用两个双端队列分别维护这个窗口的最大值和最小值&#xff1b; 当窗口扩大时&#xff0c;即j向右扩展时…

mysql根据用户名查询数据_MySQL 查询数据

MySQL 查询数据 MySQL 数据库使用SQL SELECT语句来查询数据。 你可以通过 mysql> 命令提示窗口中在数据库中查询数据,或者通过PHP脚本来查询数据。 语法 以下为在MySQL数据库中查询数据通用的 SELECT 语法: SELECT column_name,column_name FROM table_name [WHERE Clause…

【牛客 - 370 I 】Rinne Loves Xor(按位前缀和,异或)

题干&#xff1a; Rinne 最近学习了位运算相关的知识&#xff0c;她想运用自己学习的知识发明一个加密算法。 首先她有一个源数组 A&#xff0c;还有一个密钥数组 B&#xff0c;现在她想生成加密后的数组 C。 她发明的方法是&#xff1a;当计算CiCi的时候&#xff0c;首先将…

quartz mysql索引_分布式系统中的定时任务全解(二)

在实际项目中&#xff0c;通常需要用到定时任务(定时作业)&#xff0c;spring框架提供了很好的实现。 1、 下载spring-quartz插件包 这里默认当前系统中是集成了spring框架的基本功能的。去网上下载spring定时器的jar包&#xff0c;这里用的是quartz-all-1.8.4.jar&#xff0c…

【牛客 - 331B】炫酷五子棋(STLset 或Hash,tricks,二维map标记)

题干&#xff1a; 五子棋是一个简单的双人游戏。 小希最近在思索一种更好玩的五子棋。她希望胜利不再是谁先五子连珠谁赢&#xff0c;而变成谁落子后&#xff0c;该子与之前的子五子连珠的次数更多才能胜利。 但是如果是在普通的棋盘上&#xff0c;这个游戏又显得不是很有趣…

【牛客 - 318J】王者荣耀(dp,01背包)

题干&#xff1a; "无论何时何地&#xff0c;都会遵守约定"。"奋力逃吧"。"关于取下敌人性命这件事&#xff0c;也从不失约"。 小懒虫zmx平时最喜欢玩的游戏就是《王者荣耀》&#xff0c;在这款游戏中它也最喜欢百里守约这个英雄。最近&#x…

xodo上的笔记不见了_goodnotes 的笔记无缘无故丢失了一本,还能救回来吗?

真的什么都没有做&#xff0c;很普通的记完笔记放在那里去吃饭&#xff0c;回来的时候&#xff0c;别的笔记都没变化&#xff0c;只有我一直在用、刚记完的那一本消失了……我尝试过的方案&#xff1a;1.icloud刚开始不确定那里有没有&#xff0c;我平时是开着 icloud 对笔记的…

【牛客 - 318G】LLLYYY的数字思维 与【牛客 - 289J】这是一个沙雕题II(贪心构造)

题干&#xff1a; LLLYYY很喜欢写暴力模拟贪心思维。某一天在机房&#xff0c;他突然抛给了队友ppq一 个问题。问题如下&#xff1a; 有一个函数f ()&#xff1a; int f(int x){ int tmp 0; while(x ! 0){ tmp x % 10; x / 10; } return tmp; } 接着…

react div组件设置可点击不可点击_React面试全解

更新:收藏前点个赞亲&#xff0c;为啥我每次写的东西收藏都是赞的n倍&#xff01;&#xff01;花了一个月时间总结的React面试题 希望能帮助到你全文近万字建议保存仔细过一遍目录面试中常提的重要概念React生命周期ReduxRouter重要的方法面试中常提的重要概念1 什么是模块化是…

【牛客 - 185B】路径数量(离散数学,长度为k的路径数量,图)

题干&#xff1a; 给出一个 n * n 的邻接矩阵A. A是一个01矩阵 . A[i][j]1表示i号点和j号点之间有长度为1的边直接相连. 求出从 1 号点 到 n 号点长度为k的路径的数目. 输入描述: 第1行两个数n,k (20 ≤n ≤ 30,1 ≤ k ≤ 10) 第2行至第n1行&#xff0c;为一个邻接矩阵 …

php mysql 菜鸟_PHP 和 MySQL 基础教程(四)

PHP 和 MySQL 基础教程(四)发布时间&#xff1a;2016-06-17 来源&#xff1a; 点击:次MySQL 中的 SQL对于 MySQL &#xff0c;第一件你必须牢记的是它的每一行命令都是用分号 (;) 作为结束的&#xff0c;但……没有完全绝对的事&#xff0c;在这儿也是一样。前面我曾经讲到&…

【POJ - 1724 】ROADS (带限制的最短路 或 dfs 或 A*算法,双权值)

题干&#xff1a; N cities named with numbers 1 ... N are connected with one-way roads. Each road has two parameters associated with it : the road length and the toll that needs to be paid for the road (expressed in the number of coins). Bob and Alice use…

mysql 5.7.20 win64_Win10下MySQL5.7.20 Mysql(64位)解压版安装及bug修复

2、解压到某一文件夹&#xff0c;如“C:\Program Files\MySQL\mysql-5.7.20-winx64”3、添加环境变量(系统变量)&#xff1a;变量名&#xff1a;MYSQL_HOME变量值&#xff1a;C:\Program Files\MySQL\mysql-5.7.20-winx64&#xff1b;在系统变量path原有值后添加路径&#xff1…

【CodeForces - 474D】Flowers (线性dp)

题干&#xff1a; We saw the little game Marmot made for Moles lunch. Now its Marmots dinner time and, as we all know, Marmot eats flowers. At every dinner he eats some red and white flowers. Therefore a dinner can be represented as a sequence of several f…

mysql事务顺序重排_MySQL事务处理及字符集和校对顺序

一、事务处理 事务处理&#xff1a;是一种机制&#xff0c;管理必须成批执行的MySQL操作&#xff0c;以保证数据库不包含不完整的操作结果。用来维护数据库的完整性。利用事务处理&#xff0c;可以保证一组操作不会中途停止&#xff0c;或作为整体执行或完全不执行(除非明确指示…

mysql权重怎么配置_mysql如何按权重查询数据啊?

楼上的回答全都会错意了&#xff0c;题主意思是根据权重设定随机几率&#xff0c;例如 A 的权重为10&#xff0c;B 的权重为 5&#xff0c;这个时候随机出现 A 的几率要比出现 B 的几率高。你可以试试这个备选方案。就是先取出权重列表再去根据权重随机出来的那个权重值&#x…

【计蒜客 - 蓝桥训练】修建公路(贪心,或运算,dp)

题干&#xff1a; 蒜头国有 nn 座城市&#xff0c;编号分别为 0,1,2,3,\ldots,n-10,1,2,3,…,n−1。编号为 xx 和 yy 的两座城市之间如果要修高速公路&#xff0c;必须花费 x|yx∣y 个金币&#xff0c;其中|表示二进制按位或。 吝啬的国王想要花最少的价格修建高速公路&#…

【计蒜客 - 蓝桥训练】阶乘位数(数学,对数运算,求阶乘位数)

题干&#xff1a; 蒜头君对阶乘产生了兴趣&#xff0c;他列出了前 1010 个正整数的阶乘以及对应位数的表&#xff1a; nnn!n!位数111221361424251203672037504048403205936288061036288007 对于蒜头君来说&#xff0c;再往后就很难计算了。他试图寻找阶乘位数的规律&#xff…

mysql win10 优化设置_windows10如何优化?系统优化设置方法

windows10如何优化&#xff1f;&#xff0c;高系统效率&#xff0c;尽可能提高运行速度&#xff0c;是我们关心的问题。以下是电脑系统优化设置的4种方法&#xff0c;能够有效的提高系统的使用效率和优化系统管理&#xff0c;我们一起来看看吧&#xff01;第一招&#xff1a;删…

【牛客 - 368D】动态连通块(并查集+bitset优化)

题干&#xff1a; 小T有n个点&#xff0c;每个点可能是黑色的&#xff0c;可能是白色的。 小T对这张图的定义了白连通块和黑连通块&#xff1a; 白连通块&#xff1a;图中一个点集V&#xff0c;若满足所有点都是白点&#xff0c;并且V中任意两点都可以只经过V中的点互相到达&a…