家谱(gen)
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 227 通过数: 109
【题目描述】
现代的人对于本家族血统越来越感兴趣,现在给出充足的父子关系,请你编写程序找到某个人的最早的祖先。
【输入】
由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系由二行组成,用#name的形式描写一组父子关系中的父亲的名字,用+name的形式描写一组父子关系中的儿子的名字;接下来用?name的形式表示要求该人的最早的祖先;最后用单独的一个$表示文件结束。规定每个人的名字都有且只有6个字符,而且首字母大写,且没有任意两个人的名字相同。最多可能有1000组父子关系,总人数最多可能达到50000人,家谱中的记载不超过30代。
【输出】
按照输入的要求顺序,求出每一个要找祖先的人的祖先,格式:本人的名字+一个空格+祖先的名字+回车。
【输入样例】
#George +Rodney #Arthur +Gareth +Walter #Gareth +Edward ?Edward ?Walter ?Rodney ?Arthur $
【输出样例】
Edward Arthur Walter Arthur Rodney George Arthur Arthur
【代码分析】
#include<bits/stdc++.h> using namespace std; #define N 50100 string b[N],s1,s2;//b[i]表示编号i的名字 char ch;//在主函数定义就运行错误,不知道为啥 int fa[N],sum=0; //fa[i]保存i所在家族的最老祖先 int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } int w(string s) //将字符串转换并查集中唯一序号 { for(int i=1;i<=sum;i++) //防止重复 if(b[i]==s) return i; b[++sum]=s; return sum; } int main() { cout<<ch<<endl; for(int i=1;i<=N;i++) fa[i]=i; do { cin>>ch; switch(ch) { case'#': cin>>s1;break; case'+': cin>>s2; if(s1!=s2) fa[find(w(s2))]=find(w(s1));//利用并查集合并最早的祖先 break; case'?': cin>>s2; cout<<s2<<" "<<b[find(w(s2))]<<endl; break; } }while(ch!='$'); return 0; }