树的直径学习笔记(DFS)

树的直径

  1. 什么是树的直径?
    树的直径指树中最远的两个节点之间的距离,连接这两个节点之间的路径被称为树的最长链
  2. 树的直径的时间复杂度?
    (O(N))
  3. 原理
    我们通过两次DFS,第一次从任一点(S)出发进行DFS,找到一个离(S)最远的点(D),然后从(D)点出发,寻找离(D)点最远的点(E),(D)(E)之间的距离即为树的直径。
  4. 原理证明?
    分三种情况
    第一种,(P)在直径上,根据定义可知(PQ)为树的直径
    第二种,(P)不在直径上
    我们使用反证法

    假设(PQ)不是直径,但(AB)是直径,则(OP+OQ>OP+OB),得(OQ+OA>OB+OA),即(QA>AB),与直径定义相悖,故原命题成立
    第三种,(PQ)(AB)无交点

    依旧是反证法,(MP+MQ>MQ+MN+NB),同时减掉(MQ),得(MP>MN+NB),易知(MP+MN>NB),所以(MP+MN+NA>NB+NA)
    (MP+MN+NA>AB),与(AB)是直径矛盾,所以这种情况也不成立
  5. 代码实现
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7;

int n,m,tot = 0;
bool v[N];
int ans = 0,farp;
int ver[N],edge[N],Next[N],head[N],d[N];

void add(int x,int y,int z)
{
	ver[++tot] = y;
	edge[tot] = z;
	Next[tot] = head[x];
	head[x] = tot;
}

void dfs(int x)
{
	for(int i = head[x];i;i = Next[i])
	{
		int y = ver[i];
		int z = edge[i];
		if(v[y]) continue;
		v[y] = 1;
		d[y] = d[x] + z;
		dfs(y);
	}
}

int main()
{
	
	int x,y,z;
	cin >> n >> m;
	for(int i = 1;i <= m;i ++ )
	{
		cin >> x >> y >> z;
		add(x,y,z);
		add(y,x,z);
	}
	
	dfs(1);
	
	for(int i = 1;i <= n;i ++ )
	{
		if(d[i] > ans) ans = d[i],farp;
		d[i] = v[i] = 0;
	}
	
	ans = 0;
	dfs(farp);
	
	for(int i = 1;i <= n;i ++ )
	{
		if(d[i] > ans) ans = d[i];
	}
	cout << ans << endl;
	return 0;
}

至于为什么不学树形DP的方法,因为树形DP无法记录最长链经过的结点,时间复杂度上又不比DFS好多少,所以不介绍了(其实还是因为太弱没看懂

原文地址:https://www.cnblogs.com/breadcomplex/p/14092215.html