[树的深度] Party
Party
A company has n employees numbered from 1 to n. Each employee either has no immediate manager or exactly one immediate manager, who is another employee with a different number. An employee A is said to be the superior of another employee B if at least one of the following is true:
- Employee A is the immediate manager of employee B
- Employee B has an immediate manager employee C such that employee A is the superior of employee C.
The company will not have a managerial cycle. That is, there will not exist an employee who is the superior of his/her own immediate manager.
Today the company is going to arrange a party. This involves dividing all n employees into several groups: every employee must belong to exactly one group. Furthermore, within any single group, there must not be two employees A and B such that A is the superior of B.
What is the minimum number of groups that must be formed?
Input
The first line contains integer n (1 ≤ n ≤ 2000) — the number of employees.
The next n lines contain the integers pi (1 ≤ pi ≤ n or pi = -1). Every pi denotes the immediate manager for the i-th employee. If pi is -1, that means that the i-th employee does not have an immediate manager.
It is guaranteed, that no employee will be the immediate manager of him/herself (pi ≠ i). Also, there will be no managerial cycles.
OutputPrint a single integer denoting the minimum number of groups that will be formed in the party.
Examples5
-1
1
2
1
-1
3
For the first example, three groups are sufficient, for example:
- Employee 1
- Employees 2 and 4
- Employees 3 and 5
题意:给出n个点和他们的父结点,现在要将他们分成一些小组,小组内不能出现任何一个人的祖先,问最少可以分成几个组
思路:在一个组内不能出现一个点的祖先,也不能出现一个点的后代,因为如果出现了一个点的后代,则这个结点就是那些后代的祖先,这是不合法的
所以我们可以把深度相同的结点分位一组,最大深度就是要分的组数,因为题目的上下级关系可能会分成很多树形成一个森林,所以我们把每个结点当作树根来统计深度,最后保存一个最大的深度作为答案输出
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<queue> 5 using namespace std; 6 typedef long long ll; 7 const int amn=1e5+5; 8 int n,ans=0,m[amn],deep[amn],cnt; 9 vector<int> eg[amn]; 10 queue<int> q; 11 void bfs(int rt){ 12 while(q.size())q.pop();q.push(rt); 13 memset(deep,0,sizeof deep); 14 deep[rt]=1; 15 cnt=0; 16 while(q.size()){ 17 int u=q.front();q.pop(); 18 cnt=max(cnt,deep[u]); 19 for(int i=0;i<eg[u].size();i++){ 20 int v=eg[u][i]; 21 deep[v]=deep[u]+1; 22 q.push(v); 23 } 24 } 25 ans=max(ans,cnt); 26 } 27 int main(){ 28 scanf("%d",&n); 29 for(int i=1;i<=n;i++){ 30 scanf("%d",&m[i]); 31 if(m[i]!=-1){ 32 eg[m[i]].push_back(i); 33 } 34 } 35 ans=0; 36 for(int i=1;i<=n;i++){ 37 bfs(i); 38 } 39 printf("%d\n",ans); 40 } 41 /** 42 题意:给出n个点和他们的父结点,现在要将他们分成一些小组,小组内不能出现任何一个人的祖先,问最少可以分成几个组 43 思路:在一个组内不能出现一个点的祖先,也不能出现一个点的后代,因为如果出现了一个点的后代,则这个结点就是那些后代的祖先,这是不合法的 44 所以我们可以把深度相同的结点分位一组,最大深度就是要分的组数,因为题目的上下级关系可能会分成很多树形成一个森林,所以我们把每个结点当作树根来统计深度,最后保存一个最大的深度作为答案输出 45 **/