L2-026 小字辈
传送门
经过这么多题的反思与整理,现在重新写这种题实在太简单了

柳婼大大这里使用的是BFS,但是我用的是DFS,两者都可以,前者对于初学者可能稍微难写了一点(虽然模板性非常强)。
解题思路
- 显然建图,而且显然是邻接表,数据量是\(10^5\),邻接表处理得过来
dfs遍历我们建的图,从根节点开始,令根节点的距离为1,用d数组记录距离(深度)(辈分),每个子节点的距离等于父节点的距离加 \(1\)。
这题可以与下面的L2-031深入虎穴联系一下
tip:
以往我会采用当前深度与最大深度比较,如果相等会存进答案数组里,如果需要更新的时候,我会先清空数组再把新的数字放进去。但是其实可以先算出来最大深度,再遍历一遍,把符合条件的放进答案数组,可以省去清空数组的开销
这里给出DFS和BFS两种做法
算法一
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> f[100010];
bool vis[100010];
int d[100010];
int root;
int n;
void dfs(int u)
{
vis[u] = true;
for(auto x : f[u])
{
if(!vis[x])
{
vis[x] = true;
d[x] = d[u] + 1;
dfs(x);
}
}
}
int main()
{
cin>>n;
for(int i = 1 ; i <= n ; i++)
{
int x;cin>>x;
if(x == -1) root = i;
else f[x].push_back(i);
}
d[root] = 1;
dfs(root);
int max_d = 0;
vector<int> res;
for(int i = 1 ; i <= n ; i++) max_d = max(d[i],max_d);
for(int i = 1 ; i <= n ; i++) if(d[i] == max_d) res.push_back(i);
cout<<max_d<<endl;
for(int i = 0 ; i < res.size() ; i ++ )
{
cout<<res[i];
if(i != res.size() - 1) cout<<" ";
}
return 0;
}
算法二
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 100010;
vector<int> adj[N];
int dist[N];
int n,root;
void bfs()
{
queue<int> q;
q.push(root);
dist[root] = 1;
while(!q.empty())
{
int t = q.front();
q.pop();
for(int son : adj[t])
{
if(dist[son] == 0)
{
dist[son] = dist[t] + 1;
q.push(son);
}
}
}
}
int main()
{
cin>>n;
for(int i = 1 ; i <= n ; i++)
{
int p;cin>>p;
if(p == -1) root = i;
else adj[p].push_back(i);
}
bfs();
int max_d=0;
for(int i = 1; i <= n ; i++)
{
max_d = max(max_d,dist[i]);
}
cout<<max_d<<endl;
vector<int> res;
for(int i = 1 ; i <= n ; i++)
{
if(dist[i] == max_d)
{
res.push_back(i);
}
}
for(int i = 0 ; i < res.size() ; i ++)
{
cout<<res[i];
if(i != res.size() - 1 ) cout<<" ";
}
return 0;
}
算法三:记忆化搜索
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100010;
int f[N]; // 记录父辈
int d[N]; // 记忆化搜索:记录每个节点的深度
// 递归求深度
int getdepth(int u)
{
// 如果是老祖宗(父辈为 -1),深度为 1
if (f[u] == -1)
{
return 1;
}
// 如果已经算过了,直接返回,避免重复计算
if (d[u] != 0)
{
return d[u];
}
// 否则:我的深度 = 我父亲的深度 + 1
d[u] = getdepth(f[u]) + 1;
return d[u];
}
int main()
{
int n;
if (!(cin >> n))
{
return 0;
}
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
f[i] = x;
}
int max_depth = -1;
// 1. 先计算出所有人的深度,并找出最大深度是多少
for (int i = 1; i <= n; i++)
{
int current_depth = getdepth(i);
if (current_depth > max_depth)
{
max_depth = current_depth;
}
}
// 2. 统计所有处于最大深度的成员编号
vector<int> res;
for (int i = 1; i <= n; i++)
{
if (d[i] == max_depth)
{
res.push_back(i);
}
}
// 3. 按要求输出
cout << max_depth << endl;
for (int i = 0; i < res.size(); i++)
{
cout << res[i] << (i == res.size() - 1 ? "" : " ");
}
cout << endl;
return 0;
}

浙公网安备 33010602011771号