树的直径问题模板及其原理
Posted shuaihui520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树的直径问题模板及其原理相关的知识,希望对你有一定的参考价值。
/*树的直径是指树的最长简单路。求法: 两遍BFS :先任选一个起点BFS找到最长路的终点,再从终点进行BFS,则第二次BFS找到的最长路即为树的直径;
原理: 设起点为u,第一次BFS找到的终点v一定是树的直径的一个端点
证明: 1) 如果u 是直径上的点,则v显然是直径的终点(因为如果v不是的话,则必定存在另一个点w使得u到w的距离更长,则于BFS找到了v矛盾)
2) 如果u不是直径上的点,则u到v必然于树的直径相交(反证),那么交点到v 必然就是直径的后半段了
所以v一定是直径的一个端点,所以从v进行BFS得到的一定是直径长度
*/
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define MOD 100000000 #define inf 2147483640 using namespace std; const int maxn=30010; struct edge {int to,next,w;}e[maxn<<1]; int n,m,rt,ans,cnt,head[maxn]; void link(int u,int v,int w) { e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w; e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w; } void dfs(int x,int fa,int d) { if (ans<d) ans=d,rt=x; for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) dfs(e[i].to,x,d+e[i].w); } void init() { memset(head,0,sizeof(head)); cnt=0; } int main() { while(scanf("%d",&n)!=EOF) { init( ); for (int u,v,w,i=1;i<=n;i++) { scanf("%d%d%d",&u,&v,&w); link(u,v,w); } rt=ans=0;dfs(1,0,0); dfs(rt,0,0); printf("%d ",ans); } return 0; }
以上是关于树的直径问题模板及其原理的主要内容,如果未能解决你的问题,请参考以下文章
模板tyvjP1520 树的直径 [2017年5月计划 清北学堂Day3]
CS academy Growing Trees模板DP求树的直径