1151 LCA in a Binary Tree(30 分)
阿新 • • 發佈:2018-12-08
題目大意:給出中序序列和先序序列,再給出兩個點,求這兩個點的最近公共祖先。
解題思路:不用建樹~已知某個樹的根結點,若a和b在根結點的左邊,則a和b的最近公共祖先在當前子樹根結點的左子樹尋找,如果a和b在當前子樹根結點的兩邊,在當前子樹的根結點就是a和b的最近公共祖先,如果a和b在當前子樹根結點的右邊,則a和b的最近公共祖先就在當前子樹的右子樹尋找。中序加先序可以唯一確定一棵樹,在不構建樹的情況下,在每一層的遞迴中,可以得到樹的根結點,在此時併入lca演算法可以確定兩個結點的公共祖先~
AC 程式碼
#include<bits/stdc++.h> #include<cmath> #define mem(a,b) memset(a,b,sizeof a) #define ssclr(ss) ss.clear(), ss.str("") #define INF 0x3f3f3f3f #define MOD 1000000007 using namespace std; typedef long long ll; const int maxn=1e4+10; int in[maxn], pre[maxn]; unordered_map<int,int> pos; void lca(int inl,int inr,int prel,int a,int b) { if(inl>inr) return; int inRt=pos[pre[prel]], aIn=pos[a], bIn=pos[b]; if(inRt>aIn && inRt<bIn || inRt<aIn && inRt>bIn) printf("LCA of %d and %d is %d.\n", a, b, in[inRt]); else if(aIn==inRt || bIn==inRt) printf("%d is an ancestor of %d.\n", in[inRt], aIn==inRt ? b : a); else if(aIn>inRt && bIn>inRt) lca(inRt+1,inr,prel+1+(inRt-inl),a,b); else if(aIn<inRt && bIn<inRt) lca(inl,inRt-1,prel+1,a,b); } int main() { int q,n,a,b; scanf("%d%d",&q,&n); for(int i=1;i<=n;i++) scanf("%d",&in[i]), pos[in[i]]=i; for(int i=1;i<=n;i++) scanf("%d",&pre[i]); while(q--) { scanf("%d%d",&a,&b); if(pos[a]==0 && pos[b]==0) printf("ERROR: %d and %d are not found.\n", a, b); else if(pos[a]==0 || pos[b]==0) printf("ERROR: %d is not found.\n", pos[a] == 0 ? a : b); else lca(1,n,1,a,b); } return 0; }