P2814 家谱
题目背景
现代的人对于本家族血统越来越感兴趣。
题目描述
给出充足的父子关系,请你编写程序找到某个人的最早的祖先。
输入格式
输入由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系中父亲只有一行,儿子可能有若干行,用 #name
的形式描写一组父子关系中的父亲的名字,用 +name
的形式描写一组父子关系中的儿子的名字;接下来用 ?name
的形式表示要求该人的最早的祖先;最后用单独的一个 $
表示文件结束。
输出格式
按照输入文件的要求顺序,求出每一个要找祖先的人的祖先,格式为:本人的名字 + + + 一个空格 + + + 祖先的名字 + + + 回车。
输入输出样例 #1
输入 #1
#George
+Rodney
#Arthur
+Gareth
+Walter
#Gareth
+Edward
?Edward
?Walter
?Rodney
?Arthur
$
输出 #1
Edward Arthur
Walter Arthur
Rodney George
Arthur Arthur
说明/提示
规定每个人的名字都有且只有 6 6 6 个字符,而且首字母大写,且没有任意两个人的名字相同。最多可能有 1 0 3 10^3 103 组父子关系,总人数最多可能达到 5 × 1 0 4 5 \times 10^4 5×104 人,家谱中的记载不超过 30 30 30 代。
思路
我们可以用map,将两个数据类型都定义为string类型,用来存放儿子的父亲,同时可以用substr ( ) 函数来截取字符串,获取人名,在输入父亲时,现将名字暂存到一个变量里,在下一次输入儿子时,将儿子的父亲设为刚刚设置的变量,即:
mp[儿子] = 父亲。
随后用 find ( ) 函数来找到儿子的祖先,具体原理:只要要查找的人名出现在 mp 里 ,即:
mp.count(name) > 0
那么就说明他还是某个人的儿子,不是祖先。
最后,AC代码奉上:
题解
#include"bits/stdc++.h"
using namespace std;
map<string , string> mp;
string a, f, child;
string find(string x){ //find()用来找一个人名的祖先if(mp.count(x) > 0){ //如果数出来这个人有出现,就说明他是某人的儿子,不是祖先,继续向上找x = find(mp[x]);}return x;
}
int main(){while(true){cin>>a;if(a[0] == '#'){//父亲 f = a.substr(1, 6);//截取父亲人名}else if(a[0] == '+'){//儿子 child = a.substr(1, 6);//截取儿子人名mp[child] = f;//将儿子的父亲设为上面定义的f(父亲名)}else if(a[0] == '?'){//问题 child = a.substr(1, 6);cout<<child<<" "<<find(child)<<endl;//儿子和他的祖先}else if(a[0] == '$'){break;}}return 0;
}