1557:祖孙询问——倍增求LCA

news2024/11/23 23:59:08

【题目描述】
已知一棵 n 个节点的有根树。有 m 个询问,每个询问给出了一对节点的编号 x 和 y,询问 x 与 y 的祖孙关系。

【输入】
输入第一行包括一个整数 n 表示节点个数;

接下来 n 行每行一对整数对 a 和 b 表示 a 和 b 之间有连边。如果 b 是 −1,那么 a 就是树的根;

第 n+2 行是一个整数 m 表示询问个数;

接下来 m 行,每行两个正整数 x 和 y,表示一个询问。

【输出】
对于每一个询问,若 x 是 y 的祖先则输出 1,若 y 是 x 的祖先则输出 2,否则输出 0。

【输入样例】
10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19
【输出样例】
1
0
0
0
2
【提示】
数据范围与提示:

对于 30% 的数据,1≤n,m≤103 ;

对于 100% 的数据,1≤n,m≤4×104 ,每个节点的编号都不超过 4×104 。

分析

  1. LCA的板题,使用倍增实现的;首先一个bfs函数进行数组 depth、fa的初始化,一个lca函数来求公共祖先,先一层for让两个点跳到同一层,再一层for同时往上跳到根的下一层,最后再跳一层返回;
  2. bfs: 先获取到队头u,然后遍历他的邻边v,初始化是自根向下的,所以fa[v][0]=u,说明儿子向上再跳一步就是根节点(就不用在设置fa[u][0]的值了,它是个根还往上跳啥),所以fa的初始化,是对fa[v][i]进行赋值的(自上而下),fa[v][k]可可以跳两次实现,先跳2^(k-1) 步到 fa[v][k-1],再跳2^(k-1) 步到达fa[v][k],利用的递推的思想(2^k-1 + 2^k-1 =>2^k);
  3. lca: 先判断a,b大小,保证a在b的下面;然后开始处理让他们跳到同一层,当然判断的就是depth,让a往上跳,k从20倒着往下找,不用怕越界(有守卫),至到for结束a,b在同一层此时判断下a是否=b,等的话说明找到公共祖先了;然后处理a,b同时跳,只要fa[a][k] != fa[b][k](只要没跳到同一个结点上,就只管跳)就还继续跳,至到跳到他们最近公共祖先的下一层;最后再跳一层返回,从a向上跳一步、b向上跳一步都行;
  4. 关于哨兵的设置和作用:哨兵一共设置两份,depth[0] = 0和 fa[i,j]=0(fa默认就是0,然后把能到达的在bfs中初始化);哨兵的作用就是对跳出根节点的操作进行处理,如果a跳出去了,然后fa[a][k]=0,那么无论是depth[fa[a][k]]之间的判断,还是fa[a][k]的判断,如果跳出根节点,自然不满足当时的if条件;
  5. 吐槽下这个题的假数据范围,需要多开一点(多开一万还不行,那就直接N再乘10),不然会被卡RE、WA;下图为yxc的思路描述:
    在这里插入图片描述
#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 400010, M = 400010 * 2;

int n, m;
int h[N], e[N], ne[N], idx;
int q[N];
//fa[i,j]表示从i向上走 2^j 步能到的点;depth表示深度
int depth[N], fa[N][21];// 2^16 >40010

void add(int a, int b) {
    e[++idx] = b, ne[idx] = h[a], h[a] = idx;
}

//初始化depth、fa
void bfs(int root) {
    memset(depth, 0x3f, sizeof depth);
    //哨兵:depth[0] = 0,f[i,j]默认就是0了
    depth[0] = 0;
    int hh = 0, tt = 0;
    //第一个点——根节点
    q[0] = root;
    depth[root] = 1;
    while (hh <= tt) {
        int u = q[hh++];
        for (int i = h[u]; ~i; i = ne[i]) {
            int v = e[i];
            //如果u,v相差不是一层,说明v还没被搜过,加队列
            if (depth[v] > depth[u] + 1) {
                depth[v] = depth[u] + 1;
                q[++tt] = v;
                //初始化fa,对v开始的进行处理(自上而下)
                fa[v][0] = u;
                for (int k = 1; k <= 20; ++k) {
                    //先跳2^(k-1)步到f[v][k-1],再跳2^(k-1)步
                    fa[v][k] = fa[fa[v][k - 1]][k - 1];
                }
            }
        }
    }
}

//求两个点的公共祖先
int lca(int a, int b) {
    //a要在b下面
    if (depth[a] < depth[b])
        swap(a, b);
    //1. a先跳到同一层(一个数肯定能通过二进制表示,这层for结束就到了同一层)
    for (int k = 20; k >= 0; --k) {
        //a先向上跳2^k步
        
        //不用怕k=16或者20起始值太大,有哨兵,不怕他第一次跳太远,导致直接跳出根节点,如果跳出根节点,f[i][j]=0会出手的
        //哨兵的作用:如果f[a][k]跳出了根节点,那么左边就是depth[0]=0,自然不满足当前if,i--找下一个i
        if (depth[fa[a][k]] >= depth[b]) {//=时候,直接跳到同一层,后序就进不了if了
            //a赋上新位置,继续往上跳
            a = fa[a][k];
        }
    }
    //找到公共祖先
    if (a == b)
        return a;
    //2. a,b同时往上跳,至到他们最近公共祖先的下一层
    for (int k = 20; k >= 0; --k) {
        //说明还没跳到公共祖先(没跳到同一个结点,原目的也就不想让他们直接跳到公共祖先),就一直跳
        //哨兵的作用:如果a跳出去了,b肯定也跳出去了,因为同一层开始跳的,然后fa[a][k]=0,0!=0自然不满足当前的if,i--
        if (fa[a][k] != fa[b][k]) {
            //更新这次跳到的新位置
            a = fa[a][k];
            b = fa[b][k];
        }
    }
    //当前在公共祖先的下一层,再往上跳一层即可
    return fa[a][0];//fa[b][0]也是可以的
}

int main() {
    memset(h, -1, sizeof h);
    scanf("%d", &n);
    int root = 0; //根节点
    for (int i = 0; i < n; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        if (b == -1)
            root = a;
        else
            add(a, b), add(b, a);//无向边
    }
    bfs(root);
    cin >> m;
    while (m--) {
        int x, y;
        scanf("%d%d", &x, &y);
        int p = lca(x, y);
        if (p == x)
            printf("1\n");
        else if (p == y)
            printf("2\n");
        else
            printf("0\n");
    }
    return 0;
}

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

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

相关文章

Lattice Diamond关于原语的使用

Lattice Diamond关于原语的使用前言一、原语基本概念&#xff08;一&#xff09;简介&#xff08;二&#xff09;常用原语1.时钟相关原语2.差分输入/输出原语3.接口相关原语二、Lattice原语&#xff08;一&#xff09;原语使用&#xff08;二&#xff09;IP调用&#xff08;三&…

线性代数中的特征值和特征向量

一.几个基本概念 现将下文需要运用到的一些概念进行解释说明以便读者更好理解 1.特征值与特征向量 其中&#xff0c;我们要注意两点&#xff1a; &#xff08;1&#xff09;A是方阵&#xff08;对于非方阵&#xff0c;是没有特征值的&#xff0c;但会有条件数&#xff09; …

基于LMS算法的Mackey Glass时间序列预测(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 时间序列预测方法是科学、经济、工程等领域的研究重点之一。经典的时间序列预测方法在用于非线性系统预测时有一定的困难,而神…

论文投稿指南——中文核心期刊推荐(物理学2)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

【论文精度】Subdivision-Based Mesh Convolution Networks

0.摘要 卷积神经网络( CNNs )在二维计算机视觉领域取得了巨大的突破。然而&#xff0c;其不规则的结构使得直接在网格上利用卷积神经网络的潜力变得困难。细分曲面提供了层次化的多分辨率结构&#xff0c;其中一个封闭的二维流形三角网格中的每个面恰好与三个面相邻。受这两点…

2022中国企业家博鳌论坛耿明雨致白皮书

海南.博鳌于2022年11月25日至28日&#xff0c;为期三天&#xff0c;中国企业家论坛准时开幕。 此次论坛主旨以“奋进新征程 建功新时代”为主题&#xff0c;来自全国知名企业家、媒体同仁、国内权威央媒、党媒云集于此&#xff0c;在全媒体融合时代下&#xff0c;以新华社、半月…

基于python命令流及代码的Plaxis自动化建模与典型案例

有限单元法在岩土工程问题中应用非常广泛&#xff0c;很多商业软件如Plaxis/Abaqus/Comsol等都采用有限单元解法。在使用各大软件进行数值模拟建模的过程中&#xff0c;您是否发现GUI界面中重复性的点击输入工作太繁琐&#xff1f;从而拖慢了设计或方案必选进程&#xff1f; 主…

电脑无法打开相机照片怎么解决?

相机拍照后的照片&#xff0c;大部分人把照片保存在电脑上&#xff0c;这样就可以把相机的内存卡腾空出来进行新的一轮拍摄。最近有新朋友询问如果电脑上的照片打不开怎么办&#xff1f; 首先我们要了解什么情况下电脑的照片会打不开&#xff0c;原因可能有以下几种&#xff1…

YOLO v2

参考 YOLO v2 - 云社区 - 腾讯云 摘要 我们引入了YOLO9000&#xff0c;一个最先进的&#xff0c;实时的物体检测系统&#xff0c;可以检测超过9000个物体类别。首先&#xff0c;我们提出了YOLO检测方法的各种改进&#xff0c;既有新颖的&#xff0c;也有来自之前工作的。改进…

R语言中敏感性和特异性、召回率和精确度作为选型标准的华夫图案例

精度和查全率源自信息检索&#xff0c;但也用于机器学习设置中。但是&#xff0c;在某些情况下&#xff0c;使用精度和查全率可能会出现问题。在这篇文章中&#xff0c;我将讨论召回率和精确度的缺点&#xff0c;并说明为什么敏感性和特异性通常更有用。 定义 对于类别0和1的…

新中式穿搭:柯罗芭KLOVA传承极致东方美

随着欧美风和日韩风的穿搭流行&#xff0c;如今在中国的大地再次刮起了一股复古风潮&#xff0c;而作为千年文化的沉淀&#xff0c;新中式风格的穿搭更加注重独特意义上的风格体现&#xff0c;通过传统服饰和新式的现代裁剪&#xff0c;款式的组合&#xff0c;符合现代人的一种…

【HBU】2022秋线上作业——第六次——查找排序选择判断

目录 判断题&#x1f496; 1-1 希尔排序是稳定的算法。F 1-2 在散列表中&#xff0c;所谓同义词就是具有相同散列地址的两个元素。 T 1-3 对AVL树中的任一结点&#xff0c;其左、右子树的高度一定是一样的。 F 1-4 任何最小堆中从根结点到任一叶结点路径上的所有结点是有…

期末前端web大作业——基于HTML当当图书网项目的设计与实现 网上书城 网上书店 在线书店网页

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

再来一弹 | 美格智能强化5G阵营,推出国产芯Mini PCIe封装5G模组SRM810

近年来&#xff0c;我国在政策上加强顶层设计&#xff0c;根植移动物联网发展沃土&#xff0c;在技术上加快5G基础设施建设、深化4G网络应用&#xff0c;建立了以5G为核心、4G LTE Cat.1/NB-IoT等协同发展的移动物联网综合生态体系&#xff0c;全面开启了“物超人”时代新纪元。…

Linux搭建ELK日志收集系统构建:Filebeat+Redis+Logstash+Elasticse

Linux搭建ELK日志收集系统构建&#xff1a;FilebeatRedisLogstashElasticse 一、ELK概述&#xff1a; ELK是一组开源软件的简称&#xff0c;其包括Elasticsearch、Logstash 和 Kibana。ELK最近几年发展迅速&#xff0c;已经成为目前最流行的集中式日志解决方案。 Elasticsea…

Git和Github

一、Git和Github概念 Git是本地电脑上运行的版本控制软件&#xff0c;Github是基于Git打造的版本控制网站&#xff0c;可以理解为是一个全球网站仓库。Git是由Linux开发的 Github由于是网站所有具有网站的属性&#xff0c;同时也具有版本控制的属性。Github有三个概念&#x…

SpringBoot+Vue实现美食交流网站的设计与实现

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat J…

新加坡国际学校IB均分持续全球霸榜

新加坡的教育水平和资源一直是亚洲翘楚&#xff0c;甚至在中小学教育方面赶超很多欧美国家。这其中&#xff0c;新加坡国际学校作为进入海外名校的捷径进入了中国父母的视野。 当然了新加坡有很多国际学校&#xff0c;虽说新加坡整体教育水平比较高&#xff0c;但是总归是有在平…

不同材质皮革皮衣皮裤应对西南盆地地区冬季低温阴冷湿冷气候会有什么样的效果?

PU皮 ​PU 是英文poly urethane的缩写&#xff0c;化学中文名称“聚氨酯”。 PU皮革就是聚氨酯成份的表皮。广泛适用于做箱包、服装、鞋、车辆和家具的装饰&#xff0c;它已日益得到市场的肯定&#xff0c;其应用范围之广&#xff0c;数量之大&#xff0c;品种之多&#xff0c…

关于git、gitlab、jenkins你知道多少?

目录 &#x1f341;git简述 &#x1f341;git基本命令 &#x1f341;分支 &#x1f341;Gitlab &#x1f990;安装Gitlab &#x1f990;部署Gitlab &#x1f990;git常用命令 &#x1f341;CI&CD &#x1f341;Jenkins &#x1f990;安装Jenkins &#x1f990;部署Jenkins …