最近公共祖先

描述

小Ho最近發現了一個神奇的網站!雖然還不夠像58同城那樣神奇,但這個網站仍然讓小Ho樂在其中,但這是爲什麼呢?

“爲什麼呢?”小Hi如是問道,在他的觀察中小Ho已經沉迷這個網站一週之久了,甚至連他心愛的樹玩具都棄置一邊。

“嘿嘿,小Hi,你快過來看!”小Ho招呼道。

“你看,在這個對話框裏輸入我的名字,在另一個對話框裏,輸入你的名字,再點這個查詢按鈕,就可以查出來……什麼!我們居然有同一個祖祖祖祖祖爺爺?”

“誒,真是誒……這個網站有點厲害啊。”小Hi不由感嘆道。

“是啊,這是什麼算法啊,這麼厲害!”小Ho也附和道。

“別2,我說的是他能弄到這些數據很厲害,而人類的繁殖樹這種層數比較淺的樹對這類算法的要求可是簡單的不得了,你都能寫出來呢!”小Hi道。

“啊?我也能寫出來?可是……該從哪開始呢?”小Ho困惑了。

小Ho要面臨的問題是這樣的,假設現在他知道了N個人的信息——他們的父親是誰,他需要對於小Hi的每一次提問——兩個人的名字,告訴小Hi這兩個人的是否存在同一個祖先,如果存在,那麼他們的所有共同祖先中輩分最低的一個是誰?

提示:不着急,慢慢來,另外我有一個問題:挖掘機技術哪家強?!

       × Close        

提示:不着急,慢慢來,另外我有一個問題:挖掘機技術哪家強?!

小Hi道:“這個問題也應該是樹結構許許多多問題中頗爲經典的一個了,如果就簡單的將父子關係視作樹結構中的父子結點關係的話,這個問題其實就是在問樹中兩個結點層數最高的公共祖先——也就是所謂的最近公共祖先,而這個問題有非常多的解決方法,分別適合於不同的場景,像在線算法離線算法什麼的現在說給你聽你也不一定能夠很快理解。”

“但是……你不是說我能夠寫出來的麼?”小Ho納悶了。

“所以說我們慢慢來不要急,先教你個最簡單的法子。”小Hi如是說道。

“最簡單的法子……如果數據量不大的話,我完全可以直接將這兩個人的祖先全部找出來,然後取它們的交集,然後再找到其中輩分最低的一個不就行了。”小Ho思考了會這般說道。

小Hi點了點頭道:“差不多就是這樣!當然你也先將一個人的祖先全都標記出來,然後順着另一個的父親一直向上找,直到找到第一個被標記過的結點,便是它們的最近公共祖先結點了。”

“原來這麼簡單!”小Ho笑道:“那我先去寫着了。”

       Close      

輸入

每個測試點(輸入文件)有且僅有一組測試數據。

每組測試數據的第1行爲一個整數N,意義如前文所述。

每組測試數據的第2~N+1行,每行分別描述一對父子關係,其中第i+1行爲兩個由大小寫字母組成的字符串Father_i, Son_i,分別表示父親的名字和兒子的名字。

每組測試數據的第N+2行爲一個整數M,表示小Hi總共詢問的次數。

每組測試數據的第N+3~N+M+2行,每行分別描述一個詢問,其中第N+i+2行爲兩個由大小寫字母組成的字符串Name1_i, Name2_i,分別表示小Hi詢問中的兩個名字。

對於100%的數據,滿足N<=10^2,M<=10^2, 且數據中所有涉及的人物中不存在兩個名字相同的人(即姓名唯一的確定了一個人)。

輸出

對於每組測試數據,對於每個小Hi的詢問,輸出一行,表示查詢的結果:如果根據已知信息,可以判定詢問中的兩個人存在共同的祖先,則輸出他們的所有共同祖先中輩分最低的一個人的名字,否則輸出-1。

Sample Input

11
JiaYan JiaDaihua
JiaDaihua JiaFu
JiaDaihua JiaJing
JiaJing JiaZhen
JiaZhen JiaRong
JiaYuan JiaDaishan
JiaDaishan JiaShe
JiaDaishan JiaZheng
JiaShe JiaLian
JiaZheng JiaZhu
JiaZheng JiaBaoyu
3
JiaBaoyu JiaLian
JiaBaoyu JiaZheng
JiaBaoyu LinDaiyu

Sample Output

JiaDaishan
JiaZheng
-1
#include<bits/stdc++.h>
using namespace std;
map<string,string> fa;
map<string,int> vis;
void find(string a,string b){
	vis.clear();
	string temp;
	temp=a;
	while(!temp.empty()){
		vis[temp]=1;
		temp=fa[temp];
	}
	temp=b;
	while(!temp.empty()&&!vis[temp]){
		
		temp=fa[temp];
	}
	if(temp.empty()){
		cout<<-1<<endl;
	}
	else cout<<temp<<endl;
	return ;
}
int main(){
	int t;
	cin>>t;
	string u,v;
	fa.clear();
	for(int i=1;i<=t;i++){
		cin>>u>>v;
		fa[v]=u;;
		
	}
	int n;
	cin>>n;
	while(n--){
		cin>>u>>v;
		find(u,v);
	}
	return 0;
	
}

首先用string非常適合的,我不是很熟,而想成並查集,只能說明親戚關係而不能輸出。

還有不知道爲什麼提交一直WA,已經確定正確的代碼提交也出現了問題。我懷疑評測的東西出了問題。

要是有什麼錯,請不吝賜教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章