题目描述
对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大。例如下图左边的树(图 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;
}