0
点赞
收藏
分享

微信扫一扫

愿天下有情人都是失散多年的兄妹----两种方法

老榆 2022-04-21 阅读 68

 1.题目

法一:DFS+并查集

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100010;

struct Node
{
    int father;                             // 父亲
    int mather;                             // 母亲
    char sex;                               // 性别
}a[N];


int n, k;
int i, j;                                   // 遍历
int id, father, mather;                     // 孩子,父,母
char sex;                                   // 性别
int x, y;                                   // 需要判断的两个人

int pre[N];                               // 并查集数组


int find(int x)
{
    if(x != pre[x]) pre[x] = find(pre[x]);
    return pre[x];
}

void Union(int a, int b)
{
    if (b == -1)
        return;
    pre[find(b)] = find(a);
}

bool dfs(int x, int y, int age)
{
    if ( x == -1 || y == -1)
        return true;
    if (age > 5)
        return true;
    if (x == y)
        return false;
    else
        return dfs(a[x].father, a[y].father, age + 1) && dfs(a[x].father, a[y].mather, age + 1) && dfs(a[x].mather, a[y].father, age + 1) && dfs(a[x].mather, a[y].mather, age + 1);
}

int main()
{
    for (int i = 0; i < N; i++)
    {
        pre[i] = i;
        a[i].father = -1;
        a[i].mather = -1;
    }
    cin >> n;
    while (n -- )
    {
        scanf("%d %c %d %d", &id, &sex, &father, &mather);
        a[id].father = father;
        a[id].sex = sex;
        a[id].mather = mather;

        // 将孩子与父母联系起来
        Union(id, father);
        Union(id, mather);

        // 父母的性别
        if (father != -1)
            a[father].sex = 'M';
        if (mather != -1)
            a[mather].sex = 'F';
    }
    cin >> k;
    while(k--)
    {
        scanf("%d %d", &x, &y);
        // 先判断性别
        if (a[x].sex == a[y].sex)
            puts("Never Mind");
        else
        {
            if (find(x) != find(y))
                puts("Yes");
            else if (dfs(x, y, 1))
                puts("Yes");
            else
                puts("No");
        }
    }
    return 0;
}

法二:DFS+标记

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int Inf=1e5+5;
vector<int> vec[Inf];//存关系图 
bool vis[Inf];//标记五服以内的亲属 
char sex[Inf];//记录性别 
bool flag;//标记情侣是否为近亲 
void Dfs(int x,int num)//num表示第几代,从0开始 
{
	if(num > 4)//超过五代直接退出 
		return;
	for(int i=0;i<vec[x].size();i++)
	{
		if(!vis[vec[x][i]]) 
		{
			vis[vec[x][i]]=1;//标记出现的人 
			Dfs(vec[x][i],num+1); 
		}
		else
			flag=1;//五服之内出现一样的人 
	}
}
int main() 
{
	int T;
	cin>>T;
	while(T--)
	{
		int t,fa,ma;
		char ch;
		scanf("%d ",&t);
		sex[t]=getchar();
		scanf(" %d %d",&fa,&ma);
		if(fa!=-1) //-1不用保存,避免数据处理不当导致数组越界 
		{
			vec[t].push_back(fa);//保存双亲 
			sex[fa]='M';//记录父亲性别 
		}
		if(ma!=-1)
		{
			vec[t].push_back(ma);
			sex[ma]='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;
}
举报

相关推荐

0 条评论