洛谷P2814 家谱
题目背景
现代的人对于本家族血统越来越感兴趣。
题目描述
给出充足的父子关系,请你编写程序找到某个人的最早的祖先。
输入输出格式
输入格式:
输入由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系中父亲只有一行,儿子可能有若干行,用#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代。
/* 感觉这题应该是noipT1难度,hash成一个数然后当成一个点记录出度,因为一个人的父亲只可能有一个,所以直接模拟即可,但是最后两个点TLE */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define mod 2333333 int cnt,map[2410000],du[2410000],to[5410000]; bool vis[2410000]; char s[50010][10],ch[10]; int ha(char c[]){ int res=1; for(int i=1;i<=6;i++) res=(res*31%mod+(ch[i]-'A'+1)*19%mod)%mod; return res; } int main(){ //freopen("Cola.txt","r",stdin); scanf("%s",ch); int now,cur; while(1){ if(ch[0]=='$')break; cur=ha(ch); if(!vis[cur]){ cnt++; for(int i=0;i<6;i++)s[cnt][i]=ch[i+1]; map[cur]=cnt; vis[cur]=1; } if(ch[0]=='#'){ int fa=cur; while(1){ scanf("%s",ch); if(ch[0]!='+')break; int now=ha(ch); if(!vis[now]){ cnt++; for(int i=0;i<6;i++)s[cnt][i]=ch[i+1]; map[now]=cnt; vis[now]=1; } to[now]=fa; du[now]++; } } if(ch[0]=='?'){ now=ha(ch); //map[now]=cnt; cout<<s[map[now]]<<' '; while(1){ if(du[now]==0)break; now=to[now]; } cout<<s[map[now]]<<endl; scanf("%s",ch); } } }
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define mod 2333333 int cnt,map[2410000],zu[2410000]; bool vis[2410000]; char s[50010][10],ch[10]; int ha(char c[]){ int res=1; for(int i=1;i<=6;i++)res=(res*27+ch[i]-'A'+1)%mod; return res; } int main(){ scanf("%s",ch); int now,cur; for(int i=1;i<=50000;i++)zu[i]=i; while(1){ if(ch[0]=='$')break; cur=ha(ch); if(!vis[cur]){ cnt++; for(int i=0;i<6;i++)s[cnt][i]=ch[i+1]; map[cur]=cnt; vis[cur]=1; } if(ch[0]=='#'){ int fa=cur; while(1){ scanf("%s",ch); if(ch[0]!='+')break; int now=ha(ch); if(!vis[now]){ cnt++; for(int i=0;i<6;i++)s[cnt][i]=ch[i+1]; map[now]=cnt; vis[now]=1; } zu[map[now]]=zu[map[fa]]; } } if(ch[0]=='?'){ now=ha(ch); cout<<s[map[now]]<<' '; cout<<s[zu[map[now]]]<<endl; scanf("%s",ch); } } }
#include<bits/stdc++.h> using namespace std; map<string,string>father; string fat(string x){//找爸爸 if(x!=father[x]) father[x]=fat(father[x]); return father[x]; } int main(){ char k; string f1,t; while(1){ cin>>k; if(k=='$') break; if(k=='#'){ cin>>f1; if(father[f1]=="") father[f1]=f1; continue; } else if(k=='+'){ cin>>t; father[t]=f1; } else if(k=='?'){ cin>>t; cout<<t<<' '<<fat(t)<<endl; } } return 0; }