总体来说是一道从下往上的DP+贪心;
设f[i]表示将消息传给i,i的子树全部接收到所能消耗的最小时间;
那么对于i的所有亲儿子节点j,我们会贪心地先给f[j]大的人传递,然后次大.....
可以证明,这样的答案一定是最优的;
然后f[i]=max(f[i],f[j]+cnt);
总的时间复杂度是O(n^2logn),可过;
但是还可以进一步优化(窝太懒了所以没写)
换根法,可以一遍dfs(nlogn)就求出所有的答案;
#include <bits/stdc++.h> #define inc(i,a,b) for(register int i=a;i<=b;i++) using namespace std; int head[2010],cnt; class littlestar{ public: int to,nxt; void add(int u,int v){ to=v; nxt=head[u]; head[u]=cnt; } }star[4010]; int n; int f[2010]; class node{ public: int value,pos; }; vector<node> vec[2010]; bool cmp(node x,node y) { return x.value>y.value; } void dfs(int u,int fa) { for(int i=head[u];i;i=star[i].nxt){ int v=star[i].to; if(v==fa) continue; dfs(v,u); vec[u].push_back((node){f[v],v}); } sort(vec[u].begin(),vec[u].end(),cmp); inc(j,0,(int)vec[u].size()-1){ int v=vec[u][j].pos; f[u]=max(f[u],f[v]+j+1); } } int tmp[2010]; int main() { scanf("%d",&n); inc(i,2,n){ int tmp; scanf("%d",&tmp); star[++cnt].add(tmp,i); star[++cnt].add(i,tmp); } int minn=INT_MAX; inc(i,1,n){ memset(f,0,sizeof(f)); inc(j,1,n) vec[j].clear(); dfs(i,0); if(f[i]<minn){ tmp[0]=0; tmp[++tmp[0]]=i; minn=f[i]; } else if(f[i]==minn){ tmp[++tmp[0]]=i; } } printf("%d ",minn+1); inc(i,1,tmp[0]){ printf("%d ",tmp[i]); } } /* 8 1 1 3 4 4 4 3 */