本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。
输入格式:
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。
输出格式:
首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。
输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9
思路1:
最开始想的是记录所有节点的父亲,然后从下到上链式遍历到根节点,记录深度。
用二元数对记录使最大深度发生改变的节点深度和序号,并主次排序,输出深度最深的那一批叶子。
但超时了3~4个数据点,于是优化了一下,减少重复标记,但还是超时了2个数据点。
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5+5;
int p[N], d[N]; //x的父母节点是p[x]
vector<PII> q; //存深度和序号
bool cmp(PII a, PII b){
if(a.first != b.first) return a.first > b.first; //按深度从大到小
return a.second < b.second; //深度相同按序号从小到大
}
int main() {
int n;
cin >> n;
for(int i = 1; i <= n; ++ i) {
int x;
cin >> x;
p[i] = x;
}
int max_deep = 1;
for(int i = 1; i <= n; ++ i) {
int deep = 1, u = i;
if(d[u]) continue;
d[u] = 1;
while(p[u] != -1) { //深度统计
++ deep;
u = p[u];
if(d[u] <= deep) d[u] = deep;
else break;
}
// q.push_back({deep, i});
if(max_deep <= deep) {
max_deep = deep;
q.push_back({deep, i}); //可能是最小辈的数
}
}
cout << max_deep << endl;
sort(q.begin(), q.end(), cmp);
cout << q[0].second;
for(int i = 1; i <= n; ++ i){
if(q[i].first == max_deep) cout << ' ' << q[i].second;
else break;
}
return 0;
}
思路二:
记录儿子节点,自根向下深度遍历(dfs)。
用vector记录方便一些。
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5+5;
int d[N];
vector<int> son[N], res; //son[i]里存儿子们
int max_deep = 1;
void dfs(int vex, int deep) {
if(deep > max_deep) { //之前不是最深
res.clear();
max_deep = deep;
res.push_back(vex);
} else if(deep == max_deep) //等深添加
res.push_back(vex);
for(auto t: son[vex]) dfs(t, deep+1);
}
int main() {
int n, root;
cin >> n;
for(int i = 1; i <= n; ++ i) {
int x;
cin >> x;
if(x == -1) root = i; //记录根节点
else son[x].push_back(i);
}
dfs(root, 1); //从根节点向下遍历
cout << max_deep << endl;
sort(res.begin(), res.end());
cout << res[0];
for(int i = 1; i < res.size(); ++ i) cout << ' ' << res[i];
return 0;
}