这一题测试数据较长,
实际上题目思路很简单,我们可以将其进行抽象成图的结构,
这样我们就可以用邻接链表来保存祖先的节点即可,最后利用dfs,将A的祖先标记,然后再利用dfs,检查是否已经有标记的,
如果有,那就代表在4代之内通婚,否则没有通婚,
所以dfs结束的条件就是这个搜索深度是否超过4代,
所以dfs搜索的状态就是(x,num);当前正在访问的节点,当前搜索的深度
题解
和L2-030冰岛人类似,但有的点比他容易
实现的话,很容易
数据结构:有父,有母,说明这不是一个普通的树
更像是一种图,肯定还是用存图的方法来存他
然后,利用BFS或者DFS进行搜索
- 可以把5代之内的祖先都找到,然后两个循环对比
- 利用BFS同时进行查找,在找的过程中进行标记,如果在查找的时候,发现他的一个祖先已经被查过了,这样肯定是有共同祖先
题目说的是“两个人最近的共同祖先如果在五代以内”
这一点要比冰岛人简单,冰岛人有可能一方是5代之内,另一方出5代…
很坑的是,这样正常做下来,就17分
有可能数据中的父母也被查询到,这个时候判断的是性别
不能只记录自己的性别
对于查找异性情侣是否存在近亲关系,我的思路很简单,先将其中一个人五代之内与他有亲属关系的人全部做标记,在查找另一个人五代之内的亲属,如果亲属中有人带有标记,说明这对情侣不能结婚,反之可以结婚。
方法:用二维数组或vector容器存关系图,然后对两个人深搜或广搜找出五服里所有亲属。
以第七对情侣为例:
在上面这两颗关系树中没有出现相同的亲属,所以他们没有近亲关系。输出Yes。
再以不能结婚的最后一组情侣为例:
在第三层中出现已经标记过的人,说明这两个人是近亲关系,输出No。
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
vector<int >parent[100010];
char sex[100010];
int vis[100010];
int flag;
void dfs(int nums,int id){//num表示从第几代开始,从0开始(层数)//id为编号
if(nums>=4){
return;
}else{
for(int j=0;j<parent[id].size();j++){
if(!vis[parent[id][j]]){
vis[parent[id][j]]=1;//标记出现过的人
dfs(nums+1,parent[id][j]);
}else{
flag=1;//
}
}
}
}
// void dfs(int index,int num){//num表示从第几代开始,从0开始
// if(num>=4)return;//超过5代直接退出(从0开始)
// else{
// for(int j=0;j<parent[index].size();j++){
// if(!vis[parent[index][j]]){//[parent[index][j]编号为index的父母的编号,没被访问过
// vis[parent[index][j]]=1;//标记出现的人
// dfs(parent[index][j],num+1);
// }else flag=1;//[parent[index][j]编号为index的父母的编号,被访问过
// }
// }
// }
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
int id;
char gender;
scanf("%d %c",&id,&gender);//尽量使用scanf来输入
sex[id]=gender;
int fid,mid;
scanf(" %d %d",&fid,&mid);
if(fid!=-1){
parent[id].push_back(fid);
sex[fid]='M';
}
if(mid!=-1){
parent[id].push_back(mid);
sex[mid]='F';
}
}
int m;
cin>>m;
for(int i=0;i<m;i++){
int aid,bid;
scanf("%d %d",&aid,&bid);
if(sex[aid]==sex[bid])
cout<<"Never Mind"<<endl;
else{
memset(vis,0,sizeof(vis));
vis[aid]=1;
vis[bid]=1;
flag=0;
//以下标为x的元素为根节点,第一层,遍历树,将5代以内的亲戚都做上标记
dfs(0,aid);
//dfs(aid,0);
//以下标为y的元素为根节点,第一层,遍历树,在5代以内遍历时遇到标记,就说明和x有5代以内的亲戚
dfs(0,bid);
//dfs(bid,0);
if(flag){//flag==1---有5代以内的标记亲戚
cout<<"No"<<endl;
}else{
cout<<"Yes"<<endl;
}
}
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int maxn=100010;
char sex[maxn];//记录性别
vector<int> parent[maxn];//存关系图
bool vis[maxn];//标记五服以内的亲属
bool flag;//标记情侣是否是近亲
void dfs(int index,int num){//num表示从第几代开始,从0开始
if(num>=4)return;//超过5代直接退出(从0开始)
else{
for(int j=0;j<parent[index].size();j++){
if(!vis[parent[index][j]]){//[parent[index][j]编号为index的父母的编号,没被访问过
vis[parent[index][j]]=1;//标记出现的人
dfs(parent[index][j],num+1);
}else flag=1;//[parent[index][j]编号为index的父母的编号,被访问过
}
}
}
int main()
{
int T;//(给的信息)总对数24
cin>>T;
while(T--){
int id,f,m;
char gender;
scanf("%d %c",&id,&gender);//00001 M 01111 -1
sex[id]=gender;
scanf(" %d %d",&f,&m);
if(f!=-1){//-1不用保存。避免数据处理不当导致数据越界
parent[id].push_back(f);
sex[f]='M';
}
if(m!=-1){
parent[id].push_back(m);
sex[m]='F';
}
}
cin>>T;//(需要查询的)总对数
while(T--){
int x,y;
scanf("%d %d",&x,&y);
if(sex[x]==sex[y])//同性
cout<<"Never Mind"<<endl;
else{
memset(vis,0,sizeof(vis));
vis[x]=1;
vis[y]=1;
flag=0;
dfs(x,0);
dfs(y,0);
if(flag)//被标记过的说明这两人是近亲
cout<<"No"<<endl;
else
cout<<"Yes"<<endl;
}
}
return 0;
}
Code
#include <iostream>
#include <vector>
#include <set>
#include <queue>
using namespace std;
const int MAX_N = 1e5 + 5;
// 性别
vector<char> sex(MAX_N);
// 关系图
vector<int> people[MAX_N];
bool judge(int x, int y)
{
queue<int> q;
q.push(x);
q.push(y);
vector<int> v(MAX_N);
v[x] = v[y] = 1;
while (!q.empty())
{
int e = q.front();
if (v[e] >= 5)
return 1;
q.pop();
for (auto i : people[e])
{
if (v[i] != 0)
return 0;
v[i] = v[e] + 1;
q.push(i);
}
}
return 1;
}
int main()
{
int N;
cin >> N;
while (N--)
{
int x;
char c;
int a, b;
cin >> x >> c >> a >> b;
sex[x] = c;
if (~a)
{
sex[a] = 'M';
people[x].push_back(a);
}
if (~b)
{
sex[b] = 'F';
people[x].push_back(b);
}
}
cin >> N;
while (N--)
{
int x, y;
cin >> x >> y;
if (sex[x] == sex[y])
cout << "Never Mind\n";
else
{
if (judge(x, y))
cout << "Yes\n";
else
cout << "No\n";
}
}
return 0;
}