【1151】LCA in a Binary Tree (30分)【倍增法解决LCA】

简介: 增法的介绍可以先看下https://blog.csdn.net/lw277232240/article/details/72870644详细介绍倍增法

倍增法的介绍可以先看下

https://blog.csdn.net/lw277232240/article/details/72870644详细介绍倍增法

https://zhyack.github.io/posts/2015_12_22_LCA-Binary-Lifting-Note.html 这个博客分块介绍得也不错

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>  
#include<map>
#include<vector>
#include<queue> 
using namespace std;
struct Node{//结点类
  int data,father,level;//点权值,父结点在pre中的下标,深度
  Node(int d=0,int f=-1,int l=0):data(d),father(f),level(l){}
};
const int MAX=10005;
Node pre[MAX];//pre[i]为当前结点i的父节点
int n,m,in[MAX];
//确定每个结点的父节点和深度
void createTree(int root,int left,int right,int father,int level){
  if(left>right)
    return;
  int i=left;
  while(i<=right && in[i]!=pre[root].data)
    ++i;//找到根结点在中序遍历序列中的位置i
  pre[root]=Node(pre[root].data,father,level);
  //确定当前子树根结点的父结点和深度
  createTree(root+1,    left,i-1,   root,    level+1);//递归处理左子树
  createTree(root+1+i-left,   i+1,right,   root,    level+1);
}
int main(){   
  int m,n,a,b;
  scanf("%d %d",&m,&n);//测试m对结点,树共n个结点
  for(int i=0;i<n;i++){
    scanf("%d",&in[i]);//存储中序序列
  }
  for(int i=0;i<n;i++)
    scanf("%d",&pre[i].data);
  createTree(0,0,n-1,-1,0);
  for(int i=0;i<m;i++){
    int a,b;
    scanf("%d%d",&a,&b);//找a和b两个结点的LCA
    int ia=n,ib=n;
    for(int i=0;i<n;i++){//找到两个结点在pre数组的下标
      if(pre[i].data==a)
        ia=i;
      if(pre[i].data==b)
        ib=i;
    }
    if(ia==n&&ib==n){
      printf("ERROR: %d and %d are not found.\n",a,b);
    }else if(ia==n){
      printf("ERROR: %d is not found.\n",a);
    }else if(ib==n){
      printf("ERROR: %d is not found.\n",b);
    }else{
      bool f=true;//true表示a的深度更大
      if(pre[ia].level <pre[ib].level){//让ia指向深度更大的结点
        swap(ia,ib);
        f=false;
      }
      while(pre[ia].level>pre[ib].level)//将二者调整到同一深度
        ia=pre[ia].father;
      if(ia==ib){
        printf("%d is an ancestor of %d.\n",pre[ia].data,f?a:b);
      }else{
        while(ia!=ib){//ia,ib同时向上调整,直至二者指向同一结点
          ia=pre[ia].father;
          ib=pre[ib].father;
        }
        printf("LCA of %d and %d is %d.\n",a,b,pre[ia].data);
      }
    }
  }
  system("pause");
    return 0;   
}
相关文章
|
存储 容器
华为机试HJ41:称砝码(深度优先遍历dfs-Depth First Search)
华为机试HJ41:称砝码(深度优先遍历dfs-Depth First Search)
154 0
|
机器学习/深度学习 C++
【PAT甲级 - C++题解】1151 LCA in a Binary Tree
【PAT甲级 - C++题解】1151 LCA in a Binary Tree
76 0
牛客hot100--BM24---二叉树的中序遍历(中等难度)
牛客hot100--BM24---二叉树的中序遍历(中等难度)
138 0
牛客hot100--BM24---二叉树的中序遍历(中等难度)
牛客hot100--BM25---二叉树的后序遍历(简单难度)
牛客hot100--BM25---二叉树的后序遍历(简单难度)
89 0
牛客hot100--BM25---二叉树的后序遍历(简单难度)
牛客hot100--BM23---二叉树的前序遍历(简单难度)
牛客hot100--BM23---二叉树的前序遍历(简单难度)
130 0
牛客hot100--BM23---二叉树的前序遍历(简单难度)
|
人工智能 vr&ar
SPOJ - COT Count on a tree(主席树 LCA)
SPOJ - COT Count on a tree(主席树 LCA)
100 0
CF191C——Fools and Roads(树上边差分+LCA)
CF191C——Fools and Roads(树上边差分+LCA)
130 0
重链剖分求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。 输入格式 第一行包含三个正整数 N,M,SN,M,S,分别表示树的结点个数、询问的个数和树根结点的序号。 接下来 N-1N−1 行每行包含两个正整数 x, yx,y,表示 xx 结点和 yy 结点之间有一条直接连接的边(数据保证可以构成树)。 接下来 MM 行每行包含两个正整数 a, ba,b,表示询问 aa 结点和 bb 结点的最近公共祖先。 输出格式 输出包含 MM 行,每行包含一个正整数,依次为每一个询问的结果。
157 0
重链剖分求LCA
[Nowcoder] network | Tarjan 边双连通分量 | 缩点 | LCA倍增优化 | 并查集
题目描述 A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are connected directly or indirectly by successive links, so data can be transformed between any two computers.
127 0
[Nowcoder] network | Tarjan 边双连通分量 | 缩点 | LCA倍增优化 | 并查集
【1115】Counting Nodes in a BST (30分)【BST建树 DFS】
【1115】Counting Nodes in a BST (30分)【BST建树 DFS】 【1115】Counting Nodes in a BST (30分)【BST建树 DFS】
112 0
下一篇
DataWorks