树的直径总结【模板】
2015-08-18 19:49
295 查看
[b]树的直径:[/b]一棵树中从一个节点到另一个节点的一条最长的路径,这条路径可以只是这个树上的部分节点,也可以是所有节点(主要看这棵树的连接方式)在这个路径上任意节点的分岔不予考虑
求法:先任意选择一个节点a当做起点来找到距离这个点最远的端点b(这两点之间的路径上所有边的权值和最大),然后再以b节点为起点找到距离b点最远的节点c此时b点到c点的距离就是这棵树上路径最长的距离。
实现:因为求树的直径题目数据量往往比较大,所以用邻接表来储存数据;至于对两个端点的查找通过bfs实现,先将第一次选择的起点a队然后开始搜索与a连接的所有边,并将权值存入dis[]数组 dis[x]=dis[top]+edge[i].w(dis[x]指的是当前搜索到的点与之前与它相 连的搜索过边的总权值,dis[top]是指当前搜索到的点的之前与它相连的搜索过边的总权值,edge[i].w是点top到当前搜索到的点 的连线的权值)完成于对当前点的搜索后,将其入队,然后对下一个点进行此操作,每次搜索时,同时将最大的权值存入sum中如此重复直至队列为空,这样这个搜素结束后,sum的值就是a点到距离其最远的点b的总权值之和;此时再以b为起点进行第二次搜索(第 二次搜 索步骤与第一次相同)
邻接表不会?点我
求法:先任意选择一个节点a当做起点来找到距离这个点最远的端点b(这两点之间的路径上所有边的权值和最大),然后再以b节点为起点找到距离b点最远的节点c此时b点到c点的距离就是这棵树上路径最长的距离。
实现:因为求树的直径题目数据量往往比较大,所以用邻接表来储存数据;至于对两个端点的查找通过bfs实现,先将第一次选择的起点a队然后开始搜索与a连接的所有边,并将权值存入dis[]数组 dis[x]=dis[top]+edge[i].w(dis[x]指的是当前搜索到的点与之前与它相 连的搜索过边的总权值,dis[top]是指当前搜索到的点的之前与它相连的搜索过边的总权值,edge[i].w是点top到当前搜索到的点 的连线的权值)完成于对当前点的搜索后,将其入队,然后对下一个点进行此操作,每次搜索时,同时将最大的权值存入sum中如此重复直至队列为空,这样这个搜素结束后,sum的值就是a点到距离其最远的点b的总权值之和;此时再以b为起点进行第二次搜索(第 二次搜 索步骤与第一次相同)
邻接表不会?点我
#include<stdio.h> #include<string.h> #include<queue> #define MAX 100000 using namespace std; int head[MAX]; int vis[MAX];//标记当前节点是否已经用过 int dis[MAX];//记录最长距离 int n,m,ans; int sum;//记录最长路径的长度 int aga; struct node { int u,v,w; int next; }edge[MAX]; void add(int u,int v,int w)//向邻接表中加边 { edge[ans].u=u; edge[ans].v=v; edge[ans].w=w; edge[ans].next=head[u]; head[u]=ans++; } void getmap() { int i,j; int a,b,c; ans=0; memset(head,-1,sizeof(head)); while(m--) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } } void bfs(int beg) { queue<int>q; memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); int i,j; while(!q.empty()) q.pop(); aga=beg; sum=0; vis[beg]=1; q.push(beg); int top; while(!q.empty()) { top=q.front(); q.pop(); for(i=head[top];i!=-1;i=edge[i].next) { if(!vis[edge[i].v]) { dis[edge[i].v]=dis[top]+edge[i].w; vis[edge[i].v]=1; q.push(edge[i].v); if(sum<dis[edge[i].v]) { sum=dis[edge[i].v]; aga=edge[i].v; } } } } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { getmap(); bfs(1);//搜索最长路径的一个端点 bfs(aga);//搜索另一个端点 printf("%d\n",sum); } return 0; }
相关文章推荐
- Linux等待队列wait_queue_head_t和wait_queue_t
- qt编译错误 _main 中被引用
- Linux内核配置(转)
- 类型“System.Net.Http.HttpResponseMessage”在未被引用的程序集中定
- 显示转换static_cast、const_cast、reinterpret_cast、dynamic_cast详解
- C语言之文件操作05——矩阵(数据)的读取方法
- LVS快速搭建教程
- iOS安全系列之一:HTTPS
- [转]让uboot的tftp支持上传功能
- poj2513(欧拉回路)
- poj - 1426-Find The Multiple-BFS
- 最大子数组和(最大子段和)
- 大龄屌丝自学笔记--Java零基础到菜鸟--004
- 数学概念——H 最美素数
- 首次开机时的默认动态壁纸
- HDOJ 2112 HDU Today(最短路,dijkstra算法)
- [TOJ 2663] Concert Hall Scheduling
- Raw-OS互斥的源代码分析的量的Mutex
- Linux下更改系统时区及时间
- 学习书籍