并查集和map
题目描述
给出充足的父子关系,请你编写程序找到某个人的最早的祖先。
输入格式
输入由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系中父亲只有一行,儿子可能有若干行,用 #name 的形式描写一组父子关系中的父亲的名字,用 +name 的形式描写一组父子关系中的儿子的名字;接下来用 ?name 的形式表示要求该人的最早的祖先;最后用单独的一个 $ 表示文件结束。
输出格式
按照输入文件的要求顺序,求出每一个要找祖先的人的祖先,格式为:本人的名字 ++ 一个空格 ++ 祖先的名字 ++ 回车。
样例
输入
#George
+Rodney
#Arthur
+Gareth
+Walter
#Gareth
+Edward
?Edward
?Walter
?Rodney
?Arthur
$
输出
Edward Arthur
Walter Arthur
Rodney George
Arthur Arthur
题目分析
找自己的祖先->明显的并查集,但是又有所不同,因为我们平时学的并查集元素们都是以数字的形式出现,本题目的父亲,子代,祖先都是字符串,那我们就想到了用map<a1,a2>mp(其中a1是数组下标类型,a2是数组内容类型) 比如在这个题目中我们可以map<string,string>mp(eg.mp[Edward]=Arthur;)
之后的做法和普通并查集是一样的
#include<bits/stdc++.h>
using namespace std;
map<string,string>mp;
//map数组用来记录string1的祖先string2是谁
char s1;
string s2,sfa;
int i,j,n,m,l,k;
string find(string n)
{
if(mp[n]==n)
return n;
return mp[n]=find(mp[n]);
}
int main()
{
while(cin>>s1)
{
if(s1=='$')
return 0;//结束条件
cin>>s2;
if(s1=='#')
/*来了一个爸爸*/
{
if(mp[s2]=="")
/*如果这位爸爸是第一次出现,
他自己就是自己的爸爸 */
mp[s2]=s2;
else
/*否则,要找他的祖先,因为s2
有一种可能在之前是别人的儿子,
所以你需要用find函数找到s2的祖先*/
mp[s2]=find(s2);
sfa=s2;
/*为后来的+做准备,爸爸出现后
再出现的+就是sfa的儿子*/
}
else if(s1=='+')
mp[s2]=find(sfa);
/*find(sfa)保险起见,
我们找的是祖先的爸爸
而不是直接让mp[s2]=sfa;
*/
else if(s1=='?')
cout<<s2<<" "<<find(mp[s2])<<endl;
}
}