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
更新:有个问题,五服以内是指最近公共祖先相对于两个人都是五服以内还是,只是有一个人五服以内就算。。答案是:只要一个人是五服以内就算,那就需要搜索不止5层,而是要搜完,但是这题呢保证了两个人是同辈,所以两人到最近公共祖先的距离是一样的,所以可以只搜索五层,也可以全搜,全搜的话需要标记搜索节点的代数,以便判断是多少服
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
int n,k;
int f[N],m[N],g[N];
int st[N],flag;
void dfs(int x,int t)
{
if(st[x]>0&&t<=5||st[x]>0&&st[x]<=5){
flag=true; return ;
}
st[x]=t;
if(f[x]!=-1)dfs(f[x],t+1);
if(m[x]!=-1)dfs(m[x],t+1);
}
int main()
{
cin>>n;
memset(f,-1,sizeof f);
memset(m,-1,sizeof m);
for(int i=0;i<n;++i)
{
int x,y,z;char c;cin>>x>>c>>y>>z;
f[x]=y;
m[x]=z;
g[x]=c;
if(y!=-1)g[y]='M';
if(z!=-1)g[z]='F';
}
cin>>k;
while(k--)
{
int x,y;cin>>x>>y;
if(g[x]==g[y])cout<<"Never Mind"<<endl;
else {
memset(st,0,sizeof st);
flag=false;
dfs(x,1);dfs(y,1);
if(flag)cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
}
return 0;
}
和冰岛人的区别:冰岛人只看父亲,可以通过循环来迭代判断,而这题要同时考虑父亲和母亲两个方向,因此必须要通过搜索来实现,从两个人分别搜索一遍,上限为5代,如果有重合的,那么就说明五服以内
由于对每个人,只需要知道他的父亲和母亲,即每个结点的出边是固定两条,且N<1e5,因此不需要邻接表,只需要一个结构体来数组来存储即可,或者多个int数组来分别存储父、母和性别
解法一:数组存关系
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int n,k,f[N],m[N],x,a,b,v[N];
char c,gender[N];
bool flag;
void dfs(int u,int t){
if(t>=6)return;
if(v[u]){
flag=false;return;
}
v[u]=1;
if(f[u]!=-1)dfs(f[u],t+1);
if(m[u]!=-1)dfs(m[u],t+1);
}
int main(){
cin>>n;
memset(f,-1,sizeof f);memset(m,-1,sizeof m);
for(int i=0;i<n;++i){
cin>>x>>c>>a>>b;
f[x]=a;m[x]=b;gender[x]=c;gender[a]='M';gender[b]='F';
}
cin>>k;
while(k--){
cin>>a>>b;
if(gender[a]==gender[b])cout<<"Never Mind"<<endl;
else {
flag=true;
memset(v,0,sizeof v);
dfs(a,1);dfs(b,1);
if(flag)cout<<"Yes"<<endl;else cout<<"No"<<endl;
}
}
return 0;
}
解法二:结构体数组存关系
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
class node
{
public:
char sex='N';
int f=-1;
int m=-1;
};
node ns[N];
int n,m,v[N];
bool flag;
void dfs(int u,int t)
{
if(t>=6)return;
if(u==-1)return;
if(v[u]==1){
flag=true;return;
}
v[u]=1;
dfs(ns[u].f,t+1);
dfs(ns[u].m,t+1);
}
int main()
{
cin>>n;
while(n--)
{
int a,c,d;char b;
cin>>a>>b>>c>>d;
ns[a].sex=b;
ns[a].f=c;
ns[a].m=d;
ns[c].sex='M';
ns[d].sex='F';
}
cin>>m;
while(m--)
{
int x,y;cin>>x>>y;
if(ns[x].sex==ns[y].sex)cout<<"Never Mind"<<endl;
else
{
flag=false;
memset(v,0,sizeof v);
dfs(x,1);dfs(y,1);
if(flag)cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理