省選專練之 [HAOI2009]毛毛蟲
阿新 • • 發佈:2018-11-02
題目描述
對於一棵樹,我們可以將某條鏈和與該鏈相連的邊抽出來,看上去就象成一個毛毛蟲,點數越多,毛毛蟲就越大。例如下圖左邊的樹(圖 1 )抽出一部分就變成了右邊的一個毛毛蟲了(圖 2 )。
輸入輸出格式
輸入格式:
在文字檔案 worm.in 中第一行兩個整數 N , M ,分別表示樹中結點個數和樹的邊數。
接下來 M 行,每行兩個整數 a, b 表示點 a 和點 b 有邊連線( a, b ≤ N )。你可以假定沒有一對相同的 (a, b) 會出現一次以上。
輸出格式:
在文字檔案 worm.out 中寫入一個整數 , 表示最大的毛毛蟲的大小。
簡單樹形DP。
實際本質:樹的最長鏈
點權就是枝葉長度
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; inline void read(int &x){ x=0; int f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } x*=f; } const int N=3e5+100; int ans=0; int root; int Du[N]; int val[N]; struct Front_star{ int u,v,nxt; }e[N<<2]; int first[N]; int cnt=0; void add(int u,int v){ Du[u]++; ++cnt; e[cnt].u=u; e[cnt].v=v; e[cnt].nxt=first[u]; first[u]=cnt; } int n,m; int F[N]; void DFS(int u,int fat){ if(Du[u]==1){ F[u]=1; return; } int now=0; for(int i=first[u];i;i=e[i].nxt){ int v=e[i].v; if(v==fat)continue; DFS(v,u); now=max(now,F[v]); } F[u]=now+val[u]; } void DP(int u,int fat){ int Fx=0,Sx=0; for(int i=first[u];i;i=e[i].nxt){ int v=e[i].v; if(v==fat)continue; DP(v,u); if(Sx<=F[v]){ Sx=F[v]; if(Sx>Fx)swap(Sx,Fx); } } ans=max(ans,Sx+Fx+val[u]); } int main(){ read(n); read(m); for(int i=1;i<=m;++i){ int u,v; read(u); read(v); add(u,v); add(v,u); } for(int i=1;i<=n;++i){ if(Du[i]!=1){ root=i; break; } } for(int i=1;i<=n;++i){ if(Du[i]==1||Du[i]==2)val[i]=1; else val[i]=Du[i]-1; } DFS(root,0); DP(root,0); cout<<ans; }