树的直径证明+HDU2196
首先把无向图变成一棵树,直径肯定由叶子组成。
有以下两种情况:


第一种:经过根节点,则找两个最远的叶子肯定是直径,也就是B+D。
第二种:不经过根节点,则目标的两个叶子肯定有一个不为根的公共祖先,如红点O,则在红点O下面找两个最远的叶子作为直径,找到了C+F。而很明显,这两个目标叶子中的其中一个(F)是距离根最远的叶子,因为如果两个叶子中不包含离根最远的点,则F经过根节点会找到更长的直径,矛盾。
则树的直径必然包括一个最远(深)叶子。先搜索到这个点(F),然后再搜索一次最远的点,可以得到树的直径。
这也说明,若把每个点(X)当成一个根,则直径的两个点(C+F)中的一个为X的最远点 ,所以找到直径C+F,则可以找到每个点在无向图中的最远距离:disCX or disFX
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;
int dis[],ans[];
int n,s,t;
vector<int>G[];
vector<int>L[];
void _dfs(int v)
{
for(int i=;i<G[v].size();i++){
if(!dis[G[v][i]]) {
dis[G[v][i]]=dis[v]+L[v][i];
_dfs(G[v][i]);
}//任意两个点只有一条路,所以dfs和bfs效果一样
}
}
void _finds()
{
memset(dis,,sizeof(dis));
dis[]=;_dfs();s=;
for(int i=;i<=n;i++)
if(dis[i]>dis[s]) s=i; }
void _findt()
{
memset(dis,,sizeof(dis));
dis[s]=;_dfs(s);t=;
for(int i=;i<=n;i++)
if(dis[i]>dis[t]) t=i;
for(int i=;i<=n;i++) ans[i]=dis[i]-;
}
void _tdis()
{
memset(dis,,sizeof(dis));
dis[t]=;
_dfs(t);
for(int i=;i<=n;i++)
if(dis[i]->ans[i]) ans[i]=dis[i]-;
}
int main()
{
int i,j,k,u,v;
while(~scanf("%d",&n)){
for(i=;i<=n;i++) {
G[i].clear();
L[i].clear();
}
for(i=;i<=n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(i);
L[u].push_back(v);
G[i].push_back(u);
L[i].push_back(v);
}
_finds();
_findt();
_tdis();
for(i=;i<=n;i++)
printf("%d\n",ans[i]);
}
return ;
}
树的直径证明+HDU2196的更多相关文章
- 「树的直径」BFS方法证明
选定任意一个点u,从u开始BFS求出距离u最大的点s,再从s点出发BFS到距离s最大的点t,则dis(s,t)即为树的直径 证明 其实只要找到了树的直径的一个端点,再BFS找到最远点就一定是直径的另一 ...
- 树的直径的求法即相关证明【树形DP || DFS】
学习大佬:树的直径求法及证明 树的直径 定义: 一棵树的直径就是这棵树上存在的最长路径. 给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之间的距 ...
- hdu2196 树的直径 + bfs
//Accepted 740 KB 15 ms //树的直径 //距离一个顶点最远的点一定是树的直径的一个端点 #include <cstdio> #include <cstring ...
- poj2631 求树的直径裸题
题目链接:http://poj.org/problem?id=2631 题意:给出一棵树的两边结点以及权重,就这条路上的最长路. 思路:求实求树的直径. 这里给出树的直径的证明: 主要是利用了反证法: ...
- [USACO2004][poj1985]Cow Marathon(2次bfs求树的直径)
http://poj.org/problem?id=1985 题意:就是给你一颗树,求树的直径(即问哪两点之间的距离最长) 分析: 1.树形dp:只要考虑根节点和子节点的关系就可以了 2.两次bfs: ...
- BZOJ 2282 & 树的直径
SDOI2011的Dayx第2题 题意: 在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在 ...
- HDU 4123(树的直径+单调队列)
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- CF 120F Spider 树的直径 简单题
一个男孩有n只玩具蜘蛛,每只蜘蛛都是一个树的结构,现在男孩准备把这n只小蜘蛛通过粘贴节点接在一起,形成一只大的蜘蛛.大的蜘蛛也依然是树的结构.输出大的蜘蛛的直径. 知识: 树的直径是指树上的最长简单路 ...
- POJ 1985 Cow Marathon && POJ 1849 Two(树的直径)
树的直径:树上的最长简单路径. 求解的方法是bfs或者dfs.先找任意一点,bfs或者dfs找出离他最远的那个点,那么这个点一定是该树直径的一个端点,记录下该端点,继续bfs或者dfs出来离他最远的一 ...
随机推荐
- python selenium webdriver方法封装(find_element_by)
下面是对find_element_by_就行了封装,封装之后的高级方法就是getElement() 下面是具体的代码: def getElement(self, selector): "&q ...
- C++类型前置声明
前言 本文总结了c++中前置声明的写法及注意事项,列举了哪些情况可以用前置声明来降低编译依赖. 前置声明的概念 前置声明:(forward declaration), 跟普通的声明一样,就是个声明, ...
- 《高性能CUDA应用设计与开发》--笔记
第一章 1.2 CUDA支持C与C++两种编程语言,该书中的实例采取的是Thrust数据并行API,.cu作为CUDA源代码文件,其中编译器为ncvv. 1.3 CUDA提供多种API: 数据并行 ...
- Python numpy有什么用?
NumPy is the fundamental package for scientific computing with Python.就是科学计算包. a powerful N-dimensio ...
- python webdriver 登录163邮箱发邮件加附件, 外加数据和程序分离,配置文件的方式
配置文件:UiObjectMapSendMap.ini用来存放配置信息 GetOptionSendMail.py 用来读取配信息 #encoding=utf-8from selenium.webdri ...
- AVAudioFoundation(4):音视频录制
本文转自:AVAudioFoundation(4):音视频录制 | www.samirchen.com 本文主要内容来自 AVFoundation Programming Guide. 采集设备的音视 ...
- CentOS下 Nginx1.13.5 + PHP7.1.10 + MySQL5.7.19 源码编译安装
一.安装Nginx ①安装依赖扩展 # yum -y install wget openssl* gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng l ...
- PHP搞笑注释代码-佛祖配美女
//////////////////////////////////////////////////////////////////// // _ooOoo_ // // o8888888o // / ...
- FMC简介
FMC简介 FMC ( FPGA Mezzanine Card ) 简而言之,是具有特定功能的子卡模块. Developed by a consortium of companies ranging ...
- 一年25个里程碑!免疫疗法“战胜”癌症,靠的是实力(5篇Science、6篇Nature )--转载
近几年,免疫疗法的成功使癌症治疗进入了新的时代.无论是科研界,还是商业界,都丝毫没有掩饰对这一领域的热情.2016年,Cell杂志公布的年度十大最佳论文中,免疫疗法占两席.事实上,这两项成果只是去年癌 ...