L2-016 愿天下有情人都是失散多年的兄妹 (25 分)

呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?
输入格式:

输入第一行给出一个正整数N(2 ≤ N ≤10​4​​),随后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

一开始看到题,十分懵逼,仔细思考,父母有多个孩子,父母可以离婚,孩子有一双父母,多对多关系,直接建个图,对于询问的节点,DFS或BFS五层逐一对照看有没有重复即可
这个题一开始我没有考虑存储父母节点(就是作为父母出现但是没有作为孩子出现的节点),因为我觉得父母节点的父母节点未知,那么搜索到此结束即可
坑就在这,题目会问这种父母节点能否婚配。。。


```cpp
#include <bits/stdc++.h>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <cstring>
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <string>

#define MAX 10010
#define INF 0x3f3f3f3f
#define EXP 1e-9
#define DEUBG 0
#define MOD 1000000007

using namespace std;

typedef long long ll;

int n,m,t,k;
struct node {
	string name,fa,ma;
	char sex;
}a[MAX*10];
map<string,int>mp;
string name;
string fa,ma;
string sk[MAX];
int top=0;
string sk2[MAX];
int tp2=0;
int sex[MAX*10];
int cnt=0;

void DFS(string id,int d){
	if(d==6)return ;
	int x=mp[id];
	sk[top++]=id;
	if(x==0)return ;
	
	if(a[x].fa.compare("-1")==0){
		return ;
	}
	else {
		DFS(a[x].fa,d+1);
	}
	
	if(a[x].ma.compare("-1")==0){
		return ;
	}
	else {
		DFS(a[x].ma,d+1);
	}
}

void dfs(string id,int d){
	if(d==6)return ;
	int x=mp[id];
	sk2[tp2++]=id;
	if(x==0)return ;
	
	if(a[x].fa.compare("-1")==0){
		return ;
	}
	else {
		dfs(a[x].fa,d+1);
	}
	
	if(a[x].ma.compare("-1")==0){
		return ;
	}
	else {
		dfs(a[x].ma,d+1);
	}
}


void Print(){
	for(int i=0;i<cnt;i++){
		cout<<a[i].name<<" "<<a[i].fa<<" "<<a[i].ma<<endl;
	}
}

void Print2(){
	for(int i=0;i<top;i++){
		cout << sk[i]<<endl;
	}
	printf("--------\n");
	for(int i=0;i<tp2;i++){
		cout << sk2[i]<<endl;
	}
}

int check(string id1,string id2){
	tp2=top=0;
	DFS(id1,1);
	dfs(id2,1);
//	Print2();
	for(int i=0;i<top;i++){
		for(int j=0;j<tp2;j++){
			if(sk[i].compare(sk2[j])==0){
				return 0;
			}
		}
	}
	return 1;
}

int main(){
	memset(sex,-1,sizeof(sex));
	string id1,id2;
	int ii1,ii2;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		getchar();
		cin>>a[cnt].name;
		mp[a[cnt].name]=cnt;
		getchar();
		cin>>a[cnt].sex;
		sex[cnt]= a[cnt].sex=='M'?1:2;
		getchar();
		cin>>a[cnt].fa;
		getchar();
		cin>>a[cnt].ma;
		t=cnt++;
		if(a[t].fa.compare("-1")!=0&&mp[a[t].fa]==0){
			mp[a[t].fa]=cnt;
			a[cnt].name=a[t].fa;
			a[cnt].fa=a[cnt].ma="-1";
			a[cnt++].sex='M';
		}
		if(a[t].ma.compare("-1")!=0&&mp[a[t].ma]==0){
			mp[a[t].ma]=cnt;
			a[cnt].name=a[t].ma;
			a[cnt].fa=a[cnt].ma="-1";
			a[cnt++].sex='F';
		}
	}
//	Print();
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		getchar();
		cin>>id1;
		getchar();
		cin>>id2;
		ii1=mp[id1];
		ii2=mp[id2];
		if(a[ii1].sex==a[ii2].sex){
			printf("Never Mind\n");
		}
		else if(check(id1,id2)){
			printf("Yes\n");
		}
		else {
			printf("No\n");
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值