家谱

题目背景

现代的人对于本家族血统越来越感兴趣。

题目描述

给出充足的父子关系,请你编写程序找到某个人的最早的祖先。

输入输出格式

输入格式:

 

输入由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系中父亲只有一行,儿子可能有若干行,用#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个字符,而且首字母大写,且没有任意两个人的名字相同。最多可能有1000组父子关系,总人数最多可能达到50000人,家谱中的记载不超过30代。

 

其实不看数据的格式的话,这道题就是一道不难的并查集题。但就因为是字符串并查集,才为这道题增添了不少难度。

有两种做法,一是用hash编码在解码,而是比较简洁,用map。

 

第一种用hash的方法不赖,因为只有6个字符,所以最大的hash值无论如何都不会超过1000,也无需进行mod处理。但不太好办的是解码,因为输出的是人名,并不是hash值。所以每次输出还需O(n)的时间来解码,复杂度不是很好。

 

第二种用map,这也是我个人比较喜欢的做法。直接把数组的下标和值全都定义成string类型的,就会非常方便,和普通的并查集几乎没什么不同。

但有一点需要注意,就是初始化。因为是迭代器,所以不能直接一个大for跑完把p[i] = i,况且每一个 i 还是一个字符串,不知有多少种情况。

所以采用动态初始化,第一次遇到某个字符串 i 的时候再 p[i] = i。所以还要再开一个map充当vis数组。虽然复杂度多了一个log,但以为数据最大5e4,没什么影响。

 

给一个用map的方法。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<string>
 6 #include<map>
 7 using namespace std;
 8 const int maxn = 5e4 + 5;
 9 map<string, string> p;
10 string Find(string x)
11 {
12     return x == p[x] ? x : p[x] = Find(p[x]);
13 }
14 void merge(string x, string y)        //规定x就是y的父亲 
15 {
16     string px = Find(x), py = Find(y);
17     if(px == py) return;
18     else {p[py] = px; return;}        //y的祖先py指向x的祖先px 
19 }
20 string n;
21 map<string, bool> vis;
22 int main()
23 {
24     while(1)
25     {
26         char c; cin >> c;
27         if(c == '$') break;
28         string x; cin >> x;
29         if(c == '#') 
30         {
31             if(!vis[x]) {p[x] = x; vis[x] = 1;}        //初始化 
32             n = x;            //用string就比较方便,可以直接赋值 
33         }
34         else if(c == '+') 
35         {
36             if(!vis[x]) {p[x] = x; vis[x] = 1;}     //初始化 
37             merge(n, x);
38         }
39         else cout << x << ' ' << Find(x) << endl;
40     }
41     return 0;
42 }

 

posted @ 2018-04-19 00:15  mrclr  阅读(467)  评论(1编辑  收藏  举报