1143 Lowest Common Ancestor(建树与不建两种思路)

Posted CSU迦叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1143 Lowest Common Ancestor(建树与不建两种思路)相关的知识,希望对你有一定的参考价值。

目录

解法一

解法二


解法一

这题可以不建树,直接利用BST的性质:左子树<根节点<右子树,对先序序列进行遍历,如果有某个元素大于等于u,v中较小的且小于等于u,v中较大的,则可能是根节点。

这题数据弱,直接认为这样的点是根节点也AC了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
#include<stdlib.h>
#include<time.h>
#include<vector>
#include<set>
#include<string>

using namespace std;
typedef long long LL;

const int maxn = 10007;
const int MOD = 1000000007;
const int INF = 1000000000;//INF:下确界  
const LL SUP = (1LL<<63)-1;//SUP:上确界 
const double eps = 1e-5;

int A[maxn];
int n;

map<int,int> eximp;

int main(){
	
	int pNum;
	cin>>pNum>>n;
	for(int i=0;i<n;i++){
		cin>>A[i];
		eximp[A[i]] = 1;
	}

	while(pNum--){
		int v1,v2;
		cin>>v1>>v2;
		if(eximp[v1]==0||eximp[v2]==0){
			if(eximp[v1]==1)printf("ERROR: %d is not found.\\n",v2);
			else if(eximp[v2]==1)printf("ERROR: %d is not found.\\n",v1);
			else printf("ERROR: %d and %d are not found.\\n",v1,v2);
			continue;
		}

		int LCA;
		for(int i=0;i<n;i++){
			LCA = A[i];
			if(LCA>=min(v1,v2)&&LCA<=max(v1,v2))break;
		}
		
		if(LCA==v1||LCA==v2)printf("%d is an ancestor of %d.\\n",LCA==v1?v1:v2,LCA==v1?v2:v1);
		else printf("LCA of %d and %d is %d.\\n",v1,v2,LCA);
			
			
	}

	return 0;
}

解法二

我尝试建树,然后用缩短系谱的通法找LCA,但是超时了。

代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
#include<stdlib.h>
#include<time.h>
#include<vector>
#include<set>
#include<string>

using namespace std;
typedef long long LL;

const int maxn = 10007;
const int MOD = 1000000007;
const int INF = 1000000000;//INF:下确界  
const LL SUP = (1LL<<63)-1;//SUP:上确界 
const double eps = 1e-5;

int A[maxn];
int n;

map<int,int> eximp;

struct Node{
	int v;
	Node *lchild,*rchild,*pa;
};

map<Node*,int> noToV;
map<int,Node*> vToNo;

void insert(int x,Node* &root){
	if(root==NULL){
		root = new Node;
		noToV[root] = x;
		vToNo[x] = root;
		root->v = x;
		root->lchild = root->rchild = root->pa = NULL;
		return; 
	}
	
	if(root->v>x){
		insert(x,root->lchild);
		if(!root->lchild->pa)root->lchild->pa = root;
	}
	if(root->v<x){
		insert(x,root->rchild);
		if(!root->rchild->pa)root->rchild->pa = root;
	}
	
}

int getLinkLen(Node* root){
	int len = 1;
	while(root->pa){
		root = root->pa;
		len ++;
	}
	return len;
}

Node* getLCA(Node* u,Node* v){
	int uLen = getLinkLen(u);
	int vLen = getLinkLen(v);
	while(uLen<vLen){
		v = v->pa;
		vLen --;
	}
	while(vLen<uLen){
		u = u->pa;
		uLen --;
	}
	while(v!=u){
		v = v->pa;
		u = u->pa;
	}
	return v;
}

int main(){
	
	int pNum;
	cin>>pNum>>n;
	for(int i=0;i<n;i++){
		cin>>A[i];
		eximp[A[i]] = 1;
	}
	
	Node* root = NULL;
	for(int i=0;i<n;i++){
		insert(A[i],root);
	}

	while(pNum--){
		int v1,v2;
		cin>>v1>>v2;
		if(eximp[v1]==0||eximp[v2]==0){
			if(eximp[v1]==1)printf("ERROR: %d is not found.\\n",v2);
			else if(eximp[v2]==1)printf("ERROR: %d is not found.\\n",v1);
			else printf("ERROR: %d and %d are not found.\\n",v1,v2);
			continue;
		}

		int LCA;
		Node* u = vToNo[v1];
		Node* v = vToNo[v2];
		LCA = noToV[getLCA(u,v)];
		
		if(LCA==v1||LCA==v2)printf("%d is an ancestor of %d.\\n",LCA==v1?v1:v2,LCA==v1?v2:v1);
		else printf("LCA of %d and %d is %d.\\n",v1,v2,LCA);
			
			
	}

	return 0;
}

结果

以上是关于1143 Lowest Common Ancestor(建树与不建两种思路)的主要内容,如果未能解决你的问题,请参考以下文章