PTA|小字辈

题目

本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。

输入格式:
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。

输出格式:
首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。

输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9

思路

感觉和无向图的并查集很相似都是找父母
//成员:1 2 3 4 5 6 7 8 9
//父母:2 6 5 5 -1 5 6 4 7
//第i个编号对应第i位成员的父母 == 第1个编号(即2) 对应第一位成员的父母
//第2个编号(即6)对应第二位成员的父母 == 2的父母为6
//3的父母是5,4的父母是5,5的父母为-1,6的父母是5
//最终形成图(最开始的5 的父母就是-1即祖宗,下面一次是它的儿女子孙,很像树,但不是二叉树,树的结点是父母,叶子是子女)
在这里插入图片描述

解题代码1

#include <iostream>
#define MAXN 10005 
using namespace std;
int main(){
	int N,p[MAXN],minG = maxG = 1//初始化最大最小辈分
	int g[MAXN] = {0};//记录每个成员的辈分
	int a[MAXN];
	int count=0;
	cin>>N;
	for(int i = 1 ;i<= N ;i ++){
		cin>>p[i];
		//祖宗 
		if(p[i] = -1) countinue;
		//确定父母的辈分 
		if(g[p[i]] == 0){
			g[p[i]] == maxG + 1;
			maxG++;
		}
		//更新儿女的辈分 
		g[i] = g[p[i]] + 1;
		//更新最大辈分 
		if(g[i] > maxG) maxG = g[i];
		if(g[i] < minG) minG = g[i];
	} 
	//输出辈分数目 
	cout<<minG;
	//找最小辈分存在哪些人 
	for(int i = 1; i<= N ;i ++){
		if(g[i] == minG) m[count++] = i;
	} 
	//输出最小辈分存在的人 
	for(int i = 0 ; i < count;i++){
		cout<<m[i];
		if(i < count-1) cout<<" ";
	}
	cout<<endl;
}

解题代码2

#include<iostream>
using namespace std;
int father[100000];
int beifen[100000] = {0};//所有人为0
int Find(int m){
    if(father[m] == -1) //父母是祖宗 
        beifen[m] = 1;//辈分就是 1
    else if(beifen[m] == 0)//辈分还未确定 
        beifen[m] = Find(father[m])+1; // 找父母的辈分,那自己的辈分是父母的+1 
    return beifen[m];
}
int main(){
    int n,i,j;
    int max = 0,flag = 0 , count = 0;
    cin>>n;
    for(i = 1 ; i <= n ; i++) cin>>father[i];//设置每个人是自己的父母
    for( i = 1 ; i <= n ; i++)Find(i);//找父母 
    for( i = 1 ; i <= n ; i ++)//辈分更新 
        if(beifen[i]>max)
            max = beifen[i];
    cout<<max<<endl;//输出最大辈分 
    
    for( i = 1 ; i <= n ; i++) if(beifen[i] == max) count++;//记录辈分最大的人数 
    for( i = 1 ; i <= n ; i++){
        if(beifen[i] == max){
            if(flag == count - 1) cout<<i;//flag 计数确定最大辈分人的输出格式即确保最后有无空格 
            else {
                cout<<i<<" ";
                flag += 1;
            }
        }
   }
    cout<<endl;
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值