题目背景
现代的人对于本家族血统越来越感兴趣。
题目描述
给出充足的父子关系,请你编写程序找到某个人的最早的祖先。
输入格式
输入由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系中父亲只有一行,儿子可能有若干行,用 #name 的形式描写一组父子关系中的父亲的名字,用 +name 的形式描写一组父子关系中的儿子的名字;接下来用 ?name 的形式表示要求该人的最早的祖先;最后用单独的一个 $ 表示文件结束。
输出格式
按照输入文件的要求顺序,求出每一个要找祖先的人的祖先,格式为:本人的名字 + 一个空格 + 祖先的名字 + 回车。
输入输出样例
输入 #1
#George
+Rodney
#Arthur
+Gareth
+Walter
#Gareth
+Edward
?Edward
?Walter
?Rodney
?Arthur
$
输出 #1
Edward Arthur
Walter Arthur
Rodney George
Arthur Arthur
说明/提示
规定每个人的名字都有且只有 6 个字符,而且首字母大写,且没有任意两个人的名字相同。最多可能有 10310组父子关系,总人数最多可能达到 5×10 人,家谱中的记载不超过 30 代。
方法一:巧用map处理,直接用map< string string >储存关系(first当下标,second当值),注意这里的初始化
#include<bits/stdc++.h>
using namespace std;
map<string,string> parent;
//找祖宗,路径压缩
string find(string x){
if(x==parent[x])return x;
return parent[x]=find(parent[x]);
}
string father;//father一定开在循环外面,否则father值会被重新定义
int main(){
string name;
while(cin>>name&&name[0]!='$'){
string newname;
for(int i=1;i<name.length();i++){//删掉第一个表示符
newname+=name[i];
}
string son;
if(name[0]=='#'){//是爸爸
father=newname;
if(parent[father]=="")parent[father]=father;//一定要先初始化爸爸的祖宗是自己,要不然就没法判断祖宗是谁了
}else if(name[0]=='+'){//是儿子
parent[newname]=father;//认爸爸
}else{
cout<<newname<<' '<<find(newname)<<endl;
}
}
}
方法二:给每个人编号,对编号处理,注意不能按秩合并,要不然会改变祖宗
#include<bits/stdc++.h>
using namespace std;
map<string,int> mp1;//名字,身份
map<int,string> mp2;//身份,名字
set<string> se;
long long a[100000],rank[100000];
//找祖宗,路径优化
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
int main(){
string name;
int id=-1;
int father;
for(int i=0;i<1000;i++){//初始化
a[i]=i;
}
while(cin>>name&&name[0]!='$'){
string newname;
for(int i=1;i<name.length();i++){//去掉第一个标识符
newname+=name[i];
}
if(se.count(newname)==0){//新人物,给身份
id++;
mp1[newname]=id;
mp2[id]=newname;
se.insert(newname);
}
if(name[0]=='#'){//是父亲
if(se.count(newname)==0){//新人物使用新身份
father=id;
}else{
father=mp1[newname];//旧人物用以前身份
}
}else if(name[0]=='+'){//是儿子
if(se.count(newname)==0){//新人物给身份
a[find(id)]=find(father);
}else {
a[find(mp1[newname])]=find(father);//出现过用以前身份
}
}else{//询问
cout<<newname<<" "<<mp2[find(mp1[newname])]<<endl;
}
}
return 0;
}
本文介绍了一种通过编程解决家族血统问题的方法,利用父子关系数据,采用两种不同的算法来找出一个人的最早祖先,包括使用map进行路径压缩优化和通过编号处理提高效率。

被折叠的 条评论
为什么被折叠?



