1. 程式人生 > >luogu P3174 [HAOI2009] 毛毛蟲 樹dp

luogu P3174 [HAOI2009] 毛毛蟲 樹dp

傳送門

樹形dp基礎題 求帶點權樹直徑

然後這個點權就是每個點的點度(son[])...

所以可以簡化一下

按照正常的套路維護從根開始的最長鏈和次長鏈

dp陣列存的時候+1改成+son[x]-1就可以了

所以dp[x] = maxx + maxxx + son[x] - 1

(maxx 和 maxxx 維護最長鏈和次長鏈)

同時ans取max 

TIme cost : 45min

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4
#include<cmath> 5 #include<queue> 6 #define ms(a,b) memset(a,b,sizeof a) 7 #define rep(i,a,n) for(int i = a;i <= n;i++) 8 #define per(i,n,a) for(int i = n;i >= a;i--) 9 #define inf 2147483647 10 using namespace std; 11 typedef long long ll; 12 typedef double D; 13 #define eps 1e-8 14
ll read() { 15 ll as = 0,fu = 1; 16 char c = getchar(); 17 while(c < '0' || c > '9') { 18 if(c == '-') fu = -1; 19 c = getchar(); 20 } 21 while(c >= '0' && c <= '9') { 22 as = as * 10 + c - '0'; 23 c = getchar(); 24 } 25 return
as * fu; 26 } 27 //head 28 const int N = 300003; 29 int n; 30 int head[N],nxt[N<<1],mo[N<<1],cnt; 31 int son[N]; 32 void _add(int x,int y) { 33 son[x]++; 34 mo[++cnt] = y; 35 nxt[cnt] = head[x]; 36 head[x] = cnt; 37 } 38 void add(int x,int y) { 39 if(x^y)_add(x,y),_add(y,x); 40 } 41 42 int dp[N],ans; 43 void dfs(int x,int f) { 44 int maxx = 0,maxxx = 0; 45 for(int i = head[x];i;i = nxt[i]) { 46 int sn = mo[i]; 47 if(sn == f) continue; 48 dfs(sn,x); 49 if(dp[sn] > maxx) maxxx = maxx,maxx = dp[sn]; 50 else if(dp[sn] > maxxx) maxxx = dp[sn]; 51 dp[x] = max(dp[x],dp[sn] + son[x] - 1); 52 } 53 ans = max(ans,maxx + maxxx + son[x] - 1); 54 } 55 56 int main() { 57 n = read(),read(); 58 rep(i,2,n) add(read(),read()); 59 rep(i,1,n) dp[i] = 1; 60 dfs(1,0),printf("%d\n",ans); 61 return 0; 62 }
View Code