小字辈(c/c++)本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。

输入格式:

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

输出格式:

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

输入样例:

9
2 6 5 5 -1 5 6 4 7

输出样例:

4
1 9

…我写的超时了-_-我首先用的递归,进行深度搜索,但是它测试的数据很大,就过不了测试点。。。
这道题的意思就是输入N个父节点(从1开始),其索引值(从1开始)就是其子辈。这样就形成了一棵树,辈分最小的成员就是树的最下层的叶子节点。

我的思路:因为索引值从1到N,对应一个人,没有重复,就用了一个普通数组。数组的索引就是这个人,数组的值就是它的父辈。有一个人的父辈是-1(传入dfs函数中,dfs(-1)),从它开始进入递归函数dfs(n)。
在函数中,遍历所有的节点,如果 数组[i]=n,就进入下一层:dfs(i)。意思就是,i的父辈是n,找到了n的子辈。再找i的子辈……记录辈分和编号的话,用的set。仔细想想,就差不多了。

代码如下(运行超时):

#include
#include
using namespace std;
int N;
int len;
int maxLen=-1;
int num[100000];
set s;
void dfs(int n){
	if(len>maxLen){
		maxLen=len;
		s.clear();
		s.insert(n);
	}else if(len==maxLen){
		s.insert(n);
	}
	for(int i=1;i<=N;i++){
		if(num[i]==n){
			len++;
			dfs(i);
			len--;
		}
	}
}
int main(){
	cin>>N;
	for(int i=1;i<=N;i++){
		cin>>num[i];
	}
	dfs(-1);
	cout<::iterator it = s.begin();it!=s.end();it++){
        if(it!=s.begin()){
            printf(" ");
        }
        printf("%d",*it);
    }
	return 0; 
}

然后,就是。。。别人的代码。思路很简单,最重要的是,它不会超时。它用的数组是vector v,v[num].push_back(i);意思是:num是父辈,i是子辈。
代码如下:

#include
#include
#include
using namespace std;
int maxlevel = 1;
vector> v;
set s;
void dfs(int node,int level){
    if(level>maxlevel){
        maxlevel = level;
        s.clear();
        s.insert(node);
    }else if(level == maxlevel){
    s.insert(node);
    }
    for(int i=0;i::iterator it = s.begin();it!=s.end();it++){
        if(it!=s.begin()){
            printf(" ");
        }
        printf("%d",*it);
    }
    return 0;
}

emmmm,提前祝大家六一快乐!(因为我不是小孩子啦)

一个集坚强与自信于一身的菇凉。

你可能感兴趣的:(PTA)