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

我的方法很直接,建树,搜索深度为4的都入到一个动态数组v中。然后比较两者的五服的动态数组v中是否有元素重复。

  1. 我使用了“玲姐表”来存父母节点。不用玲姐矩阵的原因是数据是稀疏的,用玲姐矩阵要遍历1e5次,这样看来使用玲姐表只用遍历2次就效率就很高。

  1. 每次bfs都会存一个距离本人的距离dis【x】,父母节点就是dis[x]+1了,控制在4内。queue用于bfs。

tips:输入关系的时候,记得给父母的性别也打上标志哦!我一开始的错误就是这个,接收了pAt的教育。这个隐藏条件还是很容易疏忽的。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;

int const N=1e6+10,M=2e8;
int n,m;
// int d[N][N];//玲姐矩阵看来有点难弄,因为需要建立奇怪的遍历方式
int h[N],e[M],ne[M],idx;//玲姐表的建立
char s[N];
//从图的角度思考,只建立有向图,然后有向图只往父母节点走,若有高祖服务
//广度优先搜索,同时限制层数,
//只搜索五层或者到头了,只建立有向边
//需要找到的是他行走5遍后的父亲与母亲,然后
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
vector<int> bfs(int x){
    vector<int> v;
    int dis[N];
    queue<int> q;
    q.push(x);
    dis[x]=0;
    while(q.size()){
        int t=q.front();
        q.pop();
        for(int  i=h[t];i!=-1;i=ne[i]){
            int j=e[i];//节点值
            dis[j]=dis[t]+1;
            if(dis[j]<=4){
//             cout<<j<<" ";
                q.push(j);//如果这个点到原点的距离小于5,就继续搜索
                v.push_back(j);//如果这个点是第五代
                //如果是五福内就可以加入
            }
        }
    }
//     puts("");
    return v;
}
int main(){
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=0;i<n;i++){
        int a,fa,ma;
        char sex;
        cin>>a>>sex>>fa>>ma;
        s[a]=sex;
        if(fa!=-1)
        add(a,fa),s[fa]='M';
        if(ma!=-1)
        add(a,ma),s[ma]='F';
    }
    cin>>m;
    while(m--){
        int x,y;
        bool f=false;
        cin>>x>>y;
        if(s[x]==s[y]){
            puts("Never Mind");
            continue;
        }
        vector<int> vx=bfs(x);
        vector<int> vy=bfs(y);//输入的每次的查询对象
        for(int i=0;i<vx.size();i++){
            for(int j=0;j<vy.size();j++){
                if(vx[i]==vy[j])
                    f=true;
            }
        }
        if(f)puts("No");
        else puts("Yes");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值