原题 照着PPT的思想做了第一道二次 动规 #include <iostream> #include <algorithm> #define MAXN 10010 using namespace std ; int pre[MAXN] , leaf[MAXN] , n , child[MAXN] , dis[MAXN][2] , m ; void Readin () { int i ; scanf ("%d" , &n) ; memset (pre , 0 , sizeof (pre)) ; memset (child , 0 , sizeof (child)) ; memset (dis , 0 , sizeof (dis)) ; for (i = 2 ; i <= n ; i ++) { scanf ("%d" , &pre[i]) ; child[pre[i]] ++ ; } for (m = 0 , i = 1 ; i <= n ; i ++) if (!child[i]) leaf[m ++] = i ; } void Comp () { int i , j , ans ; for (i = 0 ; pre[leaf[i]] ; i ++)//从叶子到根,不仅要记录最优值,还要记录次优值 { j = leaf[i] ; if (dis[j][0] + 1 >= dis[pre[j]][0]) { dis[pre[j]][1] = dis[pre[j]][0] ; dis[pre[j]][0] = dis[j][0] + 1 ; } else if (dis[j][0] + 1 > dis[pre[j]][1]) dis[pre[j]][1] = dis[j][0] + 1 ; if (!(-- child[pre[j]])) leaf[m ++] = pre[j] ; } for (i = m - 2 ; i >= 0 ; i --)//从根到叶子 { j = leaf[i] ; if (dis[j][0] + 1 == dis[pre[j]][0]) { if (dis[pre[j]][1] + 1 >= dis[j][0]) dis[j][1] = dis[j][0] , dis[j][0] = dis[pre[j]][1] + 1 ; else if (dis[pre[j]][1] + 1 > dis[j][1]) dis[j][1] = dis[pre[j]][1] + 1; } else dis[j][1] = max (dis[j][0] , dis[pre[j]][1] + 1) , dis[j][0] = dis[pre[j]][0] + 1; } for (ans = MAXN , i = 1 ; i <= n ; i ++) if (dis[i][0] < ans) ans = dis[i][0] ; for (i = 1 ; i <= n ; i ++) if (dis[i][0] == ans) printf ("%d " , i) ; } int main () { Readin () ; Comp () ; return 0 ; }