试题描述
对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大。例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 )。
输入数据
在文本文件 worma.in 中第一行两个整数 N , M ,分别表示树中结点个数和树的边数。
接下来 M 行,每行两个整数 a, b 表示点 a 和点 b 有边连接( a, b ≤ N )。你可以假定没有一对相同的 (a, b) 会出现一次以上。
输出数据
在文本文件 worma.out 中写入一个整数 , 表示最大的毛毛虫的大小。
样例输入
13 12
1 2
1 5
1 6
3 2
4 2
5 7
5 8
7 9
7 10
7 11
8 12
8 13
样例输出
11
测试数据范围
40% 的数据, N ≤ 50000
100% 的数据, N ≤ 300000
题解:
简单的树形DP啊,只是感觉要枚每一个点作根,想想发现是不用的
有两种情况
1.路径不过起始点的,显然会被统计到,因为会枚举到除fa的所有子节点
2.过起始点,说明是沿着fa的一直上去的一条路径,那么在起始点显然是会被统计到的
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 const int N=300005,INF=-2e9; 8 int gi(){ 9 int str=0;char ch=getchar(); 10 while(ch>'9' || ch<'0')ch=getchar(); 11 while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar(); 12 return str; 13 } 14 int n,f[N],head[N],m,num=0,val[N]; 15 struct Lin{ 16 int next,to; 17 }a[N<<1]; 18 void init(int x,int y){ 19 a[++num].next=head[x]; 20 a[num].to=y; 21 head[x]=num; 22 } 23 int ans=0; 24 void dfs(int x,int last){ 25 int u,mx=INF; 26 f[x]=val[x]; 27 for(int i=head[x];i;i=a[i].next){ 28 u=a[i].to; 29 if(u==last)continue; 30 dfs(u,x); 31 ans=max(ans,mx+f[u]+val[x]-1); 32 if(f[u]>mx)mx=f[u]; 33 f[x]=max(f[x],f[u]+val[x]-1); 34 } 35 } 36 int main() 37 { 38 freopen("worma.in","r",stdin); 39 freopen("worma.out","w",stdout); 40 n=gi();m=gi(); 41 int x,y; 42 for(int i=1;i<=m;i++){ 43 x=gi();y=gi(); 44 init(x,y);init(y,x); 45 val[x]++;val[y]++; 46 } 47 dfs(1,1); 48 printf("%d ",ans); 49 return 0; 50 }