题目
呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?
输入格式:
输入第一行给出一个正整数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
结尾无空行
思路
一道比较复杂的模拟题,使用结构体数组保存数据,再模仿二叉树遍历进行两次深搜。
注意点:
- 注意所有的数组空间,至少开 1 0 6 10^6 106
- 结构体数组的所有结点的父亲和母亲都要先设置为不可考,初始化-1
- 输入数据中的父亲母亲也要变成结点,并标注性别
- 标记五服存储的数组cnt和标记flag,每次循环都要初始化清零,避免影响下一组查询
代码
#include <stdio.h>
#include <string.h>
#define maxsize 100005
struct node
{
int sex; //关于性别,1表示M, 2表示F
int fa ; //初始值全为-1,设为父母不可考
int mo ;
}Node[maxsize];
int flag; //全局变量标注是否出五服
int cnt[maxsize]; //五服存储
void Find(int id, int num)
{
if(num == 4) return;
if(Node[id].fa != -1)
{
if(cnt[Node[id].fa] == 1)
{
flag = 1;
return;
}
cnt[Node[id].fa] = 1;
Find(Node[id].fa, num+1);
}
if(Node[id].mo != -1)
{
if(cnt[Node[id].mo] == 1)
{
flag = 1;
return;
}
cnt[Node[id].mo] = 1;
Find(Node[id].mo, num+1);
}
}
int main()
{
int n;
scanf("%d", &n);
for(int i=0; i<maxsize; i++)
Node[i].fa = Node[i].mo = -1;
for(int i=0; i<n; i++)
{
int id, father, mother;
char x;
scanf("%d %c %d %d", &id, &x, &father, &mother);
if(x == 'M') Node[id].sex = 1;
else if(x == 'F') Node[id].sex = 2;
Node[id].fa = father;
Node[id].mo = mother;
// 父母的相应编号,需要标性别
if(father != -1) Node[father].sex = 1;
if(mother != -1) Node[mother].sex = 2;
}
int k;
scanf("%d", &k);
while (k--)
{
int n1, n2;
scanf("%d %d", &n1, &n2);
if(Node[n1].sex == Node[n2].sex) printf("Never Mind\n");
else
{
//清零数组及标记
memset(cnt, 0 , sizeof(cnt));
flag = 0;
//分别对以n1, n2为根节点进行遍历搜索
Find(n1, 0);
Find(n2, 0);
if(flag) printf("No\n");
else printf("Yes\n");
}
}
return 0;
}