浅谈树的直径
最近一次模拟考试中,考到了树的直径,于是有空我便学了一下树的直径,从而有了这篇文章,下面谈一谈我对树的直径的理解
What is diameter of the tree(什么是树的直径?)
如下图:
其中,黑色的数字代表标号,红色的数字代表边权。
显而易见,这棵树的直径是3(直径的定义为:在无向图中,两个最远的点之间相差的距离)
那么,如果用树形dp来做,我们应该怎么做呢?
相信你很快就可以想到,我们能不能将这颗树的每颗子树分别求出来,再求出这颗树的直径呢?
That's right!我们确实可以这样做。
设dp[x]表示已x为根的子树的最大链的长度,那么设x的子节点为y1,y2,y3…,yn,那么我们可以发现一个状态转移方程
dp[x]=max(dp[x],dp[yi]+edge[yi] //如果dp[yi]为以yi为根的子树,那么再加上连接x的这条边,就构成了一个链,所以我们用这个链的长度,来更新以x为根的子树的最大链的长度
那么,树的直径为
ans = max(ans,dp[x]+dp[yi]+edge[yi])
but,这里就是最难理解的地方,其实是我太蒻了,一时半会没有想明白,
dp[x]+dp[yi]+edge[yi]是什么意思呢?其实就是当前最长链的长度在加上另外一条链的长度,看他们能否更新树的直径。为什么可以这么做呢?
因为dp[x]和dp[yi]肯定不是同一条链,那么直径肯定是要越长越好,所以还要更新dp[x]的值
代码如下
void dp(int x){
v[x]=1;
for(register int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(v[y])continue;
dp(y);
ans=max(ans,d[x]+d[y]+edge[i]);
d[x]=max(d[x],d[y]+edge[i]);
}
}
如果没有弄懂,请在下方留言或者在luogu中查询宗大大这个用户,私信我