PAT L2-016. 愿天下有情人都是失散多年的兄妹 (BFS)
L2-016. 愿天下有情人都是失散多年的兄妹
时间限制
200 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?
输入格式:
输入第一行给出一个正整数N(2 <= N <= 104),随后N行,每行按以下格式给出一个人的信息:
本人ID 性别 父亲ID 母亲ID
其中ID是5位数字,每人不同;性别M代表男性、F代表女性。如果某人的父亲或母亲已经不可考,则相应的ID位置上标记为-1。
接下来给出一个正整数K,随后K行,每行给出一对有情人的ID,其间以空格分隔。
注意:题目保证两个人是同辈,每人只有一个性别,并且血缘关系网中没有乱伦或隔辈成婚的情况。
输出格式:
对每一对有情人,判断他们的关系是否可以通婚:如果两人是同性,输出“Never Mind”;如果是异性并且关系出了五服,输出“Yes”;如果异性关系未出五服,输出“No”。
输入样例:24 00001 M 01111 -1 00002 F 02222 03333 00003 M 02222 03333 00004 F 04444 03333 00005 M 04444 05555 00006 F 04444 05555 00007 F 06666 07777 00008 M 06666 07777 00009 M 00001 00002 00010 M 00003 00006 00011 F 00005 00007 00012 F 00008 08888 00013 F 00009 00011 00014 M 00010 09999 00015 M 00010 09999 00016 M 10000 00012 00017 F -1 00012 00018 F 11000 00013 00019 F 11100 00018 00020 F 00015 11110 00021 M 11100 00020 00022 M 00016 -1 00023 M 10012 00017 00024 M 00022 10013 9 00021 00024 00019 00024 00011 00012 00022 00018 00001 00004 00013 00016 00017 00015 00019 00021 00010 00011输出样例:
Never Mind Yes Never Mind No Yes No Yes No No
这题是基础bfs,不过题目有点坑。
解题思路:因为该题说明不会出现乱伦,且只能同辈结婚。所以我们可以直接设个vis数组记录点是否重复出现就行了,如果重复出现,则肯定是近亲或者同性了。
1.注意初始化每个节点的父母,不然搜到一个点没有给出其父母,继续搜索下去,会得到初始化的值0,若有两个以上没有父母,则0会重复出现,导致误判。
2.父母也有可能同性。
这两点样例中都有体现,基本样例过了,该题就过了。
1 #include <cstdio> 2 #include <cstring> 3 #include <string> 4 #include <iostream> 5 #include <algorithm> 6 #include <vector> 7 #include <map> 8 #include <queue> 9 #include <map> 10 #include <cmath> 11 using namespace std; 12 const int inf = 0x3f3f3f3f; 13 typedef long long ll; 14 const int maxn = 1e5+10; 15 struct nod 16 { 17 int sex; 18 int fid; 19 int mid; 20 }; 21 int vis[maxn];//记录是否重复出现 22 int cnt[maxn];//判断搜到了第几代 23 map<int,nod>mp;//map存id 24 void bfs(int u,int v) 25 { 26 memset(vis,0,sizeof(vis)); 27 memset(cnt,0,sizeof(cnt)); 28 queue<int>q; 29 q.push(u); 30 q.push(v); 31 while(!q.empty()) 32 { 33 int x=q.front();q.pop(); 34 if(vis[x]) 35 { 36 // cout<<x<<endl; 37 puts("No"); 38 return ; 39 } 40 vis[x]=1; 41 if(cnt[x]<4) 42 { 43 u=mp[x].fid; 44 v=mp[x].mid; 45 if(u!=-1) 46 { 47 q.push(u); 48 cnt[u]=cnt[x]+1; 49 } 50 if(v!=-1) 51 { 52 q.push(v); 53 cnt[v]=cnt[x]+1; 54 } 55 } 56 57 } 58 puts("Yes"); 59 } 60 int main() 61 { 62 63 int n; 64 scanf("%d",&n); 65 int a,c,d; 66 char b; 67 for(int i=0;i<1e5+10;++i) //父母初始化 68 mp[i].fid=-1,mp[i].mid=-1; 69 for(int i=0;i<n;++i) 70 { 71 scanf("%d %c %d %d",&a,&b,&c,&d); 72 if(b=='M') mp[a].sex=1; 73 else mp[a].sex=0; 74 mp[a].fid=c; 75 mp[c].sex=1; //存储其父母的性别 76 mp[a].mid=d; 77 mp[d].sex=0; 78 } 79 int k; 80 scanf("%d",&k); 81 int u,v; 82 for(int i=0;i<k;++i) 83 { 84 scanf("%d%d",&u,&v); 85 if(mp[u].sex==mp[v].sex) puts("Never Mind"); 86 else bfs(u,v); 87 } 88 return 0; 89 }
反思:这道题单拉出来写,会觉得很简单,因为思路很清晰,cccc的题大多是这样。但是比赛的时候就没写出来,写出的代码又臭又长。赛后经过思考,我认为是因为比赛的时候有大量的题,而且前面的题都是手速题,很容易为了赶时间 而陷入 靠直觉狂敲不思考的状态。但是后面的搜索与图论题,动动脑筋会让代码简洁许多,想出完整的思路再敲才是高效的方法。
因此在以后比赛中要学会暂停,时间再紧张,也要休息。
卡题超过半个小时,就应该赶紧换题。