L2-016 愿天下有情人都是失散多年的兄妹 (25 分) 搜索,结构体应用
Published on 2022-11-17 23:03 in 暂未分类 with 林动

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;
    }
    
    posted @   林动  阅读(47)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · 终于写完轮子一部分:tcp代理 了,记录一下
    · 震惊!C++程序真的从main开始吗?99%的程序员都答错了
    · 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
    · 单元测试从入门到精通
    · 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
    点击右上角即可分享
    微信分享提示