题246.2022寒假天梯赛训练-7-5 冰岛人 (25 分)


题246.2022寒假天梯赛训练-7-5 冰岛人 (25 分)


一、题目

在这里插入图片描述
在这里插入图片描述

二、题解

这题我前面做的时候一直不带脑子地以为五代以外的要求是只要一方的五代以内的长辈没有另一方的长辈就好,然后就直接去世只对了测试点0。。。后来才发现,原来那个要求是要如果有这个公共祖先那他必须要满足在双方都是五代及以外。也就是说,为No的情况为公共祖先于双方都在五代以内或者一方有五代以内。

//五代以外包括五代必须是要满足任何一方的
#include <bits/stdc++.h>

using namespace std;

const int maxn=1e5+1;

map<string,int> index0;//以人的名为key,编号为value
int parent[maxn];//表示下标对应的人的父辈
int flag[maxn];//用于存储后序寻祖对应的祖先的代数

struct People
{
    string name;
    string familyname;
    int sex;
}P[maxn];

int main()
{
    fill(parent,parent+maxn,-1);
    int N;
    cin>>N;
    for(int i=0;i<N;i++)
    {
        cin>>P[i].name>>P[i].familyname;
        index0[P[i].name]=i;
    }
    for(int i=0;i<N;i++)
    {
        int pos_m,pos_f;
        string fa;
        pos_m=P[i].familyname.find("sson");
        if(pos_m!=-1)
        {
            fa=P[i].familyname.substr(0,pos_m);
            P[i].sex=1;
        }
        pos_f=P[i].familyname.find("sdottir");
        if(pos_f!=-1)
        {
            fa=P[i].familyname.substr(0,pos_f);
            P[i].sex=0;
        }
        if(pos_m==-1&&pos_f==-1)
        {
            if(P[i].familyname[P[i].familyname.length()-1]=='m')
            {
                P[i].sex=1;
            }
            else
            {
                P[i].sex=0;
            }
        }
        else
        {
            parent[i]=index0[fa];
        }
    }
    int M;
    cin>>M;
    for(int i=0;i<M;i++)
    {
        string name1,familyname1;
        string name2,familyname2;
        cin>>name1>>familyname1>>name2>>familyname2;
        int index1,index2;
        if(index0.find(name1)==index0.end()||index0.find(name2)==index0.end())//查无此人
        {
            printf("NA\n");
            continue;
        }
        else
        {
            index1=index0[name1];
            index2=index0[name2];
        }
        if(P[index1].sex==P[index2].sex)//同性
        {
            printf("Whatever\n");
            continue;
        }
        fill(flag,flag+maxn,0);
        int cnt;
        cnt=1;
        while(parent[index1]!=-1)//寻index1这个人的祖并存代
        {
            flag[index1]=cnt;//index1记为1代,这个必须标记,因为有可能这个index1就是index2这个人的祖先
            index1=parent[index1];
            cnt++;
        }
        flag[index1]=cnt;
        cnt=1;
        int ans=1;
        while(parent[index2]!=-1)//寻index2这个人的祖并比对两个人祖宗的代数
        {
            //No情况包括双方都有五代以内或者一方有五代以内
            if((flag[index2]>0&&flag[index2]<5&&cnt<5)||(flag[index2]>0&&flag[index2]<5&&cnt>=5)||(flag[index2]>=5&&cnt<5))
            {
                ans=0;
                break;
            }
            index2=parent[index2];
            cnt++;
        }
        if((flag[index2]>0&&flag[index2]<5&&cnt<5)||(flag[index2]>0&&flag[index2]<5&&cnt>=5)||(flag[index2]>=5&&cnt<5))//针对index2这个人的老祖设的判断
        {
            ans=0;
        }
        if(ans)
        {
            printf("Yes\n");
        }
        else
        {
            printf("No\n");
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值