浅谈树的直径

最近一次模拟考试中,考到了树的直径,于是有空我便学了一下树的直径,从而有了这篇文章,下面谈一谈我对树的直径的理解

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中查询宗大大这个用户,私信我

posted @ 2019-06-04 19:09  zhz小蒟蒻  阅读(360)  评论(1编辑  收藏  举报