pat1021Deepest Root (25)
2015-10-03 18:26
204 查看
题意分析:
(1)这一题型比较巧妙,直接给出一个树的拓扑结构,求出这棵树最深的根,言外之意就是指:当以这个节点为根的时候,树具有最深的深度。若这个图具有多个连通分支,就输入分支数。
(2)首先给出算法,随后证明这个算法一定能找到它所有的最深根:第一步:从任意一个节点开始进行深度优先遍历,找到离他最远的节点(可能不止一个,记为集合A);第二步:再从A中任意选一个节点出发进行深度优先遍历,找到离他最远的节点(记为集合B),最后最深根就是这两个集合的并集。
证明:第一步找出的节点一定是全局的最深根。
1根据全局最优解一定是局部最优解的原理:最后全局的最深根一定也是某个局部最优解,比如:因为全局最深的根是固定的,不失一般性,我们就把他们标为1、2、3、4、5,那么从图中中任意一点出发,例如A,从他出发找到的局部最优解一定是在1、2、3、4、5,反之,如不在,也就是说有比1、2、3、4、5更深的节点,我们假设它存在并且成为B,那么可想而知,从1到B肯定要比从1到2要深,这就与1、2、3、4、5是全局最优解矛盾,所以假设不成立。原命题成立。即局部最优解一定在1、2、3、4、5中。
2由第一步知道局部最优解是固定的,且全局最优解是局部最优解,根据这两条结论,得出:第一次遍历得到的最深的节点就是最深根
由于从最深根出发到最深的叶子节点是相互对称的,所以我们再从当前的最深根出发遍历一次得到其他的最深根,然后做一次去重即可。
(3)也可以不去重,在第二次遍历的时候直接通过层序遍历算出每个节点所在的层数存到数组中,最后再遍历一次
可能坑点:
(1)第一次遍历结束后要记得将最大深度重置为0,所有节点访问标记置为0.
(1)这一题型比较巧妙,直接给出一个树的拓扑结构,求出这棵树最深的根,言外之意就是指:当以这个节点为根的时候,树具有最深的深度。若这个图具有多个连通分支,就输入分支数。
(2)首先给出算法,随后证明这个算法一定能找到它所有的最深根:第一步:从任意一个节点开始进行深度优先遍历,找到离他最远的节点(可能不止一个,记为集合A);第二步:再从A中任意选一个节点出发进行深度优先遍历,找到离他最远的节点(记为集合B),最后最深根就是这两个集合的并集。
证明:第一步找出的节点一定是全局的最深根。
1根据全局最优解一定是局部最优解的原理:最后全局的最深根一定也是某个局部最优解,比如:因为全局最深的根是固定的,不失一般性,我们就把他们标为1、2、3、4、5,那么从图中中任意一点出发,例如A,从他出发找到的局部最优解一定是在1、2、3、4、5,反之,如不在,也就是说有比1、2、3、4、5更深的节点,我们假设它存在并且成为B,那么可想而知,从1到B肯定要比从1到2要深,这就与1、2、3、4、5是全局最优解矛盾,所以假设不成立。原命题成立。即局部最优解一定在1、2、3、4、5中。
2由第一步知道局部最优解是固定的,且全局最优解是局部最优解,根据这两条结论,得出:第一次遍历得到的最深的节点就是最深根
由于从最深根出发到最深的叶子节点是相互对称的,所以我们再从当前的最深根出发遍历一次得到其他的最深根,然后做一次去重即可。
(3)也可以不去重,在第二次遍历的时候直接通过层序遍历算出每个节点所在的层数存到数组中,最后再遍历一次
可能坑点:
(1)第一次遍历结束后要记得将最大深度重置为0,所有节点访问标记置为0.
#include <iostream> #include <string.h> #include <vector> #include <map> #include <queue> using namespace std; bool visit[10001]={0}; int level[10001]={0}; bool root[10001]={0}; int maxLength=0; map<int,vector<int> > tree; queue<int >qu; void getDeepest(int start) { qu.push(start); level[start]=1; visit[start]=1; while(!qu.empty()) { int temp=qu.front(); if(tree[temp].size()==0) { maxLength=level[temp]; break; } vector<int>::iterator ite = tree[temp].begin(); qu.pop(); for(;ite!=tree[temp].end();ite++) { if(!visit[*ite]) { qu.push(*ite); visit[*ite]=1; level[*ite]=level[temp]+1; if(level[*ite]>maxLength)maxLength=level[*ite]; } } } } int main() { int N; cin>>N; int i=1,from,to; int cnt=1; while(i<N) { cin>>from>>to; if(visit[from]&&visit[to])cnt++; visit[from]=1; visit[to]=1; tree[from].push_back(to); tree[to].push_back(from); i++; } if(cnt>1)cout<<"Error: "<<cnt<<" components"<<endl; else { memset(visit,0,sizeof(visit)); getDeepest(1); int first; for(int i=1;i<=N;i++) { if(level[i]==maxLength) { root[i]=1; first=i; } } memset(visit,0,sizeof(visit)); maxLength=0; getDeepest(first); for(int i=1;i<=N;i++) { if(level[i]==maxLength) { root[i]=1; } } for(int i=1;i<=N;i++) { if(root[i])cout<<i<<endl; } } return 0; }
相关文章推荐
- linux下django+mysql配置
- hadoop 开始时间datanode一个错误 Problem connecting to server
- Http协议基础
- kaptcha 2.0在ubuntu jre 7u79场景生成校验码失败的问题
- weak_ptr的用处
- 类与对象在内存中的分布情况
- Java多线程6:synchronized锁定类方法、volatile关键字及其他
- myeclipse 6.5使用Maven
- Fresco 源码分析(四) 后台数据返回到前台的处理 - Drawable体系的介绍(1)
- 2.由两个栈组成的队列
- Machine Learning Basics(要点)
- 常见系统服务及进程
- ISO/IEC 9899:2011 条款6.5.7——按位移位操作符
- POJ 2886 线段树单点更新
- java线程详解(一)
- 【Python】二分查找算法
- 我的常用脚本记录
- 实现android文字描边功能
- 第二章 python中重要的数据结构(下)
- Android源码之Gallery专题研究(1)