本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。
输入格式:
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。
输出格式:
首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。
输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9
写这道题的时候真是一波三折,一看题,这不是个dfs水题吗=w=,想着直接dfs搞定了,三下五除二写了个结构存数据,两个元素一个存爹,一个容器存儿子,然后输入数据的时候先进入对应i的下标存父亲,然后进入父亲的下标存儿子。。
本来是这样一个很简单的题,然后里面有一个老祖宗的父亲用-1表示,如果输入-1就进入-1下标保存儿子。但是进入-1的话会出错,结果就这一点没发现,耽误了好久(读取-1下标IDE竟然没报错我的天哪,要不然那还有这么多事)。我就换了好多种做法,一开始dfs递归搜索,结果pta
(这个破问题花了我50分钟写了三种方法,结果就少了一个continue)
然后我就蒙了,以为是递归爆栈了。就换成无限循环找-1父亲然后存层数,结果还是所有测试点运行出错,当时以为是超时出错(明明显示运行时错误啊),我就又换成BFS层序遍历存层数。然后还是运行出错,当时我就急了。感觉不对劲,是不是前面错了,然后调试IDE也没报错,给的输入样例也对。就从头一行一行的看啊,肉体调试大法。一看到这个下标会等于-1…再一看访问了…emmmmm,心情复杂,把前面的三种做法全都加了个continue,再一看三个方法ac两个,循环超时,最后我就来写这篇博了。。
得出来的结论就是。。。写代码的时候一定要小心,对于这种访问的下标一定要检查再检查有没有非法的数据,如果有没注意到的下标然后IDE还不提示,可能会走很多弯路QAQ
把ac的两种方法贴出来吧
DFS递归:
#include<iostream>
#include<vector>
using namespace std;
struct TNode
{
int father;
vector<int>child;
}List[100000];
int maxb = 1;
void dfs(vector<int>&l, int b, int s)
{
if (!(List[s].child.size()))
return;
for (int i = 0; i < List[s].child.size(); i++)
{
l[List[s].child[i]] = b;
if (b > maxb)
maxb = b;
dfs(l, b + 1, List[s].child[i]);
}
return;
}
int main()
{
int n;
cin >> n;
int root;
vector<int>level(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> List[i].father;
if (List[i].father == -1)//万恶之源!!!!!!!!!
{
root = i;
continue;
}
List[List[i].father].child.push_back(i);
}
level[root] = 1;
dfs(level, 2, root);
int flag = 1;
cout << maxb << endl;
for (int i = 1; i <= n; i++)
{
if (level[i] == maxb)
{
if (flag)
{
cout << i;
flag = 0;
}
else
cout << " " << i;
}
}
return 0;
}
竟然没超时/爆栈?
BFS层序遍历:
#include<iostream>
#include<vector>
#include<deque>
using namespace std;
struct TNode
{
int father;
vector<int>child;
}List[100000];
int maxb = 1;
void cxbl(vector<int>&l, int s)
{
deque<int>dl;
dl.push_back(s);
while (dl.size())
{
int a = dl.front();
dl.pop_front();
for (int i = 0; i < List[a].child.size(); i++)
{
l[List[a].child[i]] = l[a] + 1;
if (l[a] + 1 > maxb)
maxb = l[a] + 1;
dl.push_back(List[a].child[i]);
}
}
return;
}
int main()
{
int n;
cin >> n;
int root;
vector<int>level(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> List[i].father;
if (List[i].father == -1)//万恶之源!!!!!!!!!
{
root = i;
continue;
}
List[List[i].father].child.push_back(i);
}
level[root] = 1;
cxbl(level, root);
int flag = 1;
cout << maxb << endl;
for (int i = 1; i <= n; i++)
{
if (level[i] == maxb)
{
if (flag)
{
cout << i;
flag = 0;
}
else
cout << " " << i;
}
}
return 0;
}
BFS这个方法应该是比较科学的
IDE为什么不报错!!!!啊啊啊