zoukankan      html  css  js  c++  java
  • 树的直径学习笔记(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好多少,所以不介绍了(其实还是因为太弱没看懂

  • 相关阅读:
    Cors 跨域 共享
    关于上传视频到七牛的一些解决方案
    网站上传视频注意点
    Node.js 的环境配置
    动态加载js
    java web项目启动时自动加载自定义properties文件
    Apache Commons 工具类介绍及简单使用
    spring常用的工具类
    shiro内置过滤器研究
    抓取Js动态生成数据且以滚动页面方式分页的网页
  • 原文地址:https://www.cnblogs.com/breadcomplex/p/14092215.html
Copyright © 2011-2022 走看看