DP - 树形DP - 树的直径 - 图论 - 树 - bfs
题目大意
给出
棵树,你每次可以选择两个树,并将这两棵树的两个节点粘起来,形成一棵新的树。经过
次操作后,这
棵树就融合为了一棵树
问最后这棵树的最大直径(最长链)长度
解题思路
以前看到有些题是要求直径最短,看到这题之后松了口气
因为最后要求的是最长链,所以,每一棵树都要把自己的最长链(直径)贡献给最终答案
那么我们就把
棵树的直径粘成一段不就好了吗
换句话说:设第
棵树的直径端点为
,
表示一个将点
和点
粘起来的操作。
那么就:
最后的答案就是
棵树的直径之和了
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
const int Maxn=1010,inf=0x3f3f3f3f;
int dis[Maxn],f[Maxn];
int n,ans;
vector <int> e[Maxn];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
void dfs(int x,int fa)
{
int m1=0,m2=0;
for(int i=0;i<e[x].size();++i)
{
int y=e[x][i];
if(y==fa)continue;
dfs(y,x);
f[x]=max(f[x],f[y]+1);
int tmp=f[y]+1;
if(tmp>m1)m2=m1,m1=tmp;
else if(tmp>m2)m2=tmp;
}
dis[x]=max(m1+m2,max(m1,m2));
}
int main()
{
freopen("input.txt","r",stdin); // 注意这题提交的时候要带文件输入输出
freopen("output.txt","w",stdout);
int T=read();
while(T--)
{
n=read();
int tot=0;
for(int i=1;i<n;++i)
{
int x=read(),y=read();
e[x].push_back(y);
e[y].push_back(x);
}
dfs(1,0);
for(int i=1;i<=n;++i)
tot=max(tot,dis[i]);
ans+=tot;
for(int i=1;i<=n;++i)
{
e[i].clear();
dis[i]=f[i]=0;
}
}
printf("%d\n",ans);
return 0;
}