我的方法很直接,建树,搜索深度为4的都入到一个动态数组v中。然后比较两者的五服的动态数组v中是否有元素重复。
我使用了“玲姐表”来存父母节点。不用玲姐矩阵的原因是数据是稀疏的,用玲姐矩阵要遍历1e5次,这样看来使用玲姐表只用遍历2次就效率就很高。
每次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");
}
}