在树中寻找两个结点的最近公共祖先
hihoCoder给出的在线解法:将树转化为数组
“从树的根节点开始进行深度优先搜索,每次经过某一个点——无论是从它的父亲节点进入这个点,还是从它的儿子节点返回这个点,都按顺序记录下来。这样就把一棵树转换成了一个数组。而找到树上两个节点的最近公共祖先,无非就是找到这两个节点最后一次出现在数组中的位置所囊括的一段区间中深度最小的那个点。转换出的数组的长度其实就是边数的2倍而已,也是O(n)的级别。
#include <iostream>
#include <map>
#include <stack>
#include <string>
#include <stdio.h>
using namespace std;
int N=0;
int size = 0;
multimap<string,string> m ;
string *a;
int *depthA;
int preCalculate( int index );
string findMin(int begin, int end);
string query( string name1, string name2 );
void printMap();
void printArray();
int main(){
scanf("%d",&N);
string rootFather = "";
string father, child;
for( int i=0; i<N; i++ ){
cin>>father;
cin>>child;
pair<string,string> pa (father,child);
m.insert( pa );
if( i==0 )
rootFather = father;
}
//printMap();
size = 2*N+1;
a= new string[size];
depthA = new int[size];
a[0] = rootFather;
depthA[0] = 0;
preCalculate(0 );
//printArray();
int M=0;
scanf( "%d", &M );
for( int i=0; i<M; i++ ){
cin>>father;
cin>>child;
cout<<query( father, child )<<endl;
}
return 0;
}
int preCalculate( int index ){
string fatherName = a[index];
int depth = depthA[index];
multimap<string,string>::iterator it = m.find(fatherName);
if( it==m.end() ){
return index;
}
pair<multimap<string,string>::iterator,multimap<string,string>::iterator> p = m.equal_range(fatherName);
int nextIndex = index+1;
for( it=p.first;it!=p.second;it++){
a[nextIndex] = it->second;
depthA[nextIndex] = depth+1;
int end = preCalculate( nextIndex );
a[ ++end ] = fatherName;
depthA[ end ]= depth;
nextIndex = ++end;
}
return --nextIndex;
}
string query( string name1, string name2 ){
if( name1==name2 )
return name1;
int begin=-1, end=-1;
for( int i=0; i<size; i++ ){
if( name1==a[i] || a[i]==name2 ){
if( begin==-1 )
begin = i;
else if( a[i]==a[begin] )
begin = i;
else{
end = i;
break;
}
}
}
return findMin(begin,end);
}
string findMin(int begin, int end){
int minDepth = depthA[begin];
int minDepthIndex = begin;
for( int i=begin+1; i<=end; i++ ){
if( minDepth > depthA[i] ){
minDepth = depthA[i];
minDepthIndex = i;
}
}
return a[minDepthIndex];
}
void printMap(){
multimap<string,string>::iterator it = m.begin();
while( it!=m.end() ){
cout<<it->first<<" "<<it->second<<endl;
it++;
}
}
void printArray(){
for( int i=0; i<size; i++ ){
cout<<a[i]<<" "<<depthA[i]<<endl;
}
}