洛谷:P2814 家譜(並查集)
題目背景
現代的人對於本家族血統越來越感興趣。
題目描述
給出充足的父子關係,請你編寫程式找到某個人的最早的祖先。
輸入格式
輸入由多行組成,首先是一系列有關父子關係的描述,其中每一組父子關係中父親只有一行,兒子可能有若干行,用 #name 的形式描寫一組父子關係中的父親的名字,用 +name 的形式描寫一組父子關係中的兒子的名字;接下來用 ?name 的形式表示要求該人的最早的祖先;最後用單獨的一個 $ 表示檔案結束。
輸出格式
按照輸入檔案的要求順序,求出每一個要找祖先的人的祖先,格式為:本人的名字 ++ 一個空格 ++ 祖先的名字 ++ 回車。
輸入輸出樣例
輸入 #1
#George
+Rodney
#Arthur
+Gareth
+Walter
#Gareth
+Edward
?Edward
?Walter
?Rodney
?Arthur
$
輸出 #1
Edward Arthur
Walter Arthur
Rodney George
Arthur Arthur
思路:
第一眼看是並查集,但是看這個輸入就暈了,比較難處理,要麼就是給每個人都標上記號,否則就只能用STL裡的關聯式容器map來做了(STL大法好!),把有關係的人記成:f[兒子]=父親,這樣就能記錄他倆的關係,至於用不用並查集,我想都打了關聯式容器了,我們就可以當成這是連結串列或者一棵樹?當我們輸入兒子要找祖先時,就一直向上找他的父親,當兒子的父親也有父親是們就更新最大父親(因為現在找的父親不是祖先),如果找的這個父親向上沒有父親了,證明他就是這個家族最大的父親(也就是祖先)!
程式碼:
#include<map>
#include<iostream>
#include<cstring>
using namespace std;
map<string,string>f;//關聯式容器map!
char s;//名字前的字元,判斷關係
string x,a;
int main(){
while(s!='$'){
cin>>s;
if(s=='#') cin>>x,a=x;//如果是#號,證明是一個新父親,並用a來記錄新父親
if(s=='+') cin>>x,f[x]=a;//如果是+號,證明是當前a父親的兒子,f容器記錄x和a的關係
if(s=='?'){//是?號說明要尋找此人的祖先
cin>>x;
if(f[x].empty()){//如果此人本身就沒有父親,證明他就是自身的祖先
cout<<x<<" "<<x<<endl;
continue;
}
a=f[x];//a來記錄當前找到的最大祖先
while(!f[a].empty()) a=f[a];//如果父親上面還有父親,就更新最大父親,用a記錄
cout<<x<<" "<<a<<endl;//輸出
}
}
return 0;
}
相關文章
- 洛谷
- 並查集到帶權並查集並查集
- 洛谷P1494 [國家集訓隊]小Z的襪子(莫隊)
- 查並集
- 【並查集】【帶偏移的並查集】食物鏈並查集
- 洛谷P1422 小玉家的電費
- 並查集(一)並查集的幾種實現並查集
- 洛谷 P3366 【模板】最小生成樹(並查集+壓縮路徑(縮短到最高上一級的步驟))並查集
- 並查集(小白)並查集
- [leetcode] 並查集(Ⅱ)LeetCode並查集
- [leetcode] 並查集(Ⅲ)LeetCode並查集
- [leetcode] 並查集(Ⅰ)LeetCode並查集
- 3.1並查集並查集
- 洛谷團隊
- 並查集應用並查集
- 寫模板, 並查集。並查集
- 並查集的使用並查集
- 並查集跳躍並查集
- 各種並查集並查集
- 淺談並查集並查集
- 食物鏈(並查集)並查集
- 並查集(Union Find)並查集
- The Door Problem 並查集並查集
- 並查集練習並查集
- 洛谷——玩具謎題
- 英雄聯盟(洛谷)
- 洛谷P1786
- 洛谷P6786
- 洛谷 - P5369
- 洛谷P10725
- 洛谷P10693
- 洛谷 - P6190
- 洛谷死亡時間
- 並查集(二)並查集的演算法應用案例上並查集演算法
- 洛谷 P2249 【深基13.例1】查詢
- 並查集題目合集並查集
- 並查集深度應用並查集
- 並查集java實現並查集Java