1. 程式人生 > >洛谷P2018 消息傳遞 樹形DP

洛谷P2018 消息傳遞 樹形DP

sin con log sum iostream lib bsp dfs cst


洛谷P2018 消息傳遞

樹形DP
dp[ u ] 表示 u 節點 已經被傳到,
然後將其字節點都傳到所需要的最少時間

可知一個原則 一個樹中的子樹中如果同時開始傳,那麽最晚才能傳到的,那他肯定最先開始傳
因為本身需要的時間就大了,如果再晚一點開始,就要更晚才能結束了

也就是說從葉子向根傳,將一個樹中的子樹 按照 他們直接傳所需要的時間排序
優先傳大的,再傳小的

也就是一個點 只要負責好傳到他們的兒子那些點就夠了

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstdlib>
 4
#include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 #include <iomanip> 9 #include <vector> 10 using namespace std ; 11 12 const int maxn = 1011,inf = 1e9 ; 13 vector <int> f[maxn] ; 14 int n,mi,x,sum ; 15 int dp[maxn],ans[maxn] ;
16 17 inline void dfs(int u,int fa) 18 { 19 int cnt = 0,v ; 20 int tmp[maxn] ; 21 for(int i=0;i<f[ u ].size();i++) 22 { 23 v = f[ u ][ i ] ; 24 if(v!=fa) 25 { 26 dfs(v,u) ; 27 tmp[++cnt] = dp[ v ] ; 28 } 29 } 30 sort(tmp+1
,tmp+cnt+1) ; 31 for(int i=1;i<=cnt;i++) 32 dp[ u ] = max(dp[ u ],tmp[ i ] + cnt -i+1) ; // 其中 cnt-i+1 表示的是 傳給之前的兒子 33 //以及自身所需要的時間 34 } 35 36 int main() 37 { 38 scanf("%d",&n) ; 39 for(int i=2;i<=n;i++) 40 { 41 scanf("%d",&x) ; 42 f[x].push_back( i ) ; 43 f[i].push_back( x ) ; 44 } 45 mi = inf ; 46 for(int i=1;i<=n;i++) 47 { 48 for(int j=0;j<=n;j++) dp[ j ] = 0 ; 49 dfs( i,-1 ) ; 50 ans[ i ] = dp[ i ] ; 51 mi = min(mi,ans[ i ]) ; 52 } 53 printf("%d\n",mi+1) ; 54 55 56 for(int i=1;i<=n;i++) 57 if(ans[ i ]==mi) printf("%d ",i) ; 58 return 0 ; 59 }

洛谷P2018 消息傳遞 樹形DP