BDFZOI 树的直径

提交次数:2

涉及知识:基础图论/BFS

描述

一棵树T的“直径”定义为结点两两间距离的最大值。给定带权树T,求T的直径长度。

输入

第一行包含2个整数N、M,表示图中共有N个结点和M条无向边。(N <= 5000,M<n)
接下来M行,每行包含3个整数{u,v,w},表示有一条无向边连接结点u、v
*输入保证是无环图输出一个整数,代表直径长度

样例输入

4 3
1 2 1
2 3 2
2 4 3

样例输出

5

代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstring>
 5 using namespace std;
 6 struct node{
 7     int v, w;
 8     node(int vv, int ww):v(vv),w(ww){}
 9 };
10 struct bnode{
11     int x, step;
12     bnode(int xx, int ss):x(xx),step(ss){}
13 };
14 vector<vector<node> >tree(5005);
15 queue<bnode>q;
16 bool visited[5005];
17 int dis[5005];
18 int firstu, diameter; //第一次BFS扩展到的点
19 int n, m;
20
21 void bfs(int u){
22     memset(visited,0,sizeof(visited));
23     visited[u] = true;
24     while(!q.empty()){q.pop();}
25     q.push(bnode(u,0));
26     while(!q.empty()){
27         bnode bb = q.front();
28         for(int i = 0; i < tree[bb.x].size(); i++){
29             int next = tree[bb.x][i].v;
30             if(!visited[next]){
31                 q.push(bnode(next,bb.step+tree[bb.x][i].w));
32                 visited[next] = true;
33             }
34         }
35         dis[bb.x] = bb.step;
36         q.pop();
37     }
38     diameter = -1;
39     for(int i = 1; i <= n; i++){
40         if(dis[i]>=diameter){
41             diameter = dis[i];
42             firstu = i;
43         }
44     }
45 }
46 int main(){
47     cin>>n>>m;
48     for(int i = 1; i <= m; i++){
49         int a, b, c;
50         cin>>a>>b>>c;
51         tree[a].push_back(node(b,c));
52         tree[b].push_back(node(a,c));
53     }
54     bfs(1);
55     //cout<<firstu<<endl;
56     bfs(firstu);
57     cout<<diameter<<endl;
58     return 0;
59 }

备注:

树的直径,顾名思义,就是树上一条最长路,一个经典算法就是两次BFS。证明略,因为我不会。

先从树上任意一个点出发BFS到头,这时这个端点一定是直径的一端,证明略……这是第一遍BFS。

然后再从这个点BFS到头,找到的最长路就是直径。 这是第二遍BFS。

时间: 2024-12-29 01:40:51

BDFZOI 树的直径的相关文章

poj 1985 Cow Marathon 【树的直径】

题目:poj 1985 Cow Marathon 题意:给出一个树,让你求树的直径. 分析: 树的直径:树上两点之间的最大距离. 我们从任意一点出发,BFS一个最远距离,然后从这个点出发,在BFS一个最远距离,就是树的直径. AC代码: /* POJ:1985 Cow Marathon 2014/10/12/21:18 Yougth*/ #include <cstdio> #include <iostream> #include <algorithm> #include

poj1849(求树的直径)

题目链接:http://poj.org/problem?id=1849 题意:有一颗n个结点的带权的无向树, 在s结点放两个机器人, 这两个机器人会把树的每条边都走一遍, 但是最后机器人不要求回到出发点. 问你两个机器人走的路总长之和的最小值是多少? 分析:如果从某点出发遍历完一棵树再回来,那么所有边都会走两遍,而从某点有两个机器人出发去遍历,因为不用回来,所以最后那两个人距离越远越好,可以从树的直径上某个点背道而驰,那么这段距离(树的直径)只走了一遍,其他的要走两遍,所以ans=sum*2-l

SDUT OJ 3045 迷之图论 (树的直径)

题目地址:SDUT OJ 3045 这题比赛的时候想的差不多..但是总是觉得不对..写了一次就没再写,然后删了..当时没想到的是第二次求出来的就是最长链..当时想到的两次bfs找最大值(这一种方法其实结果也对..TAT..),还有找到点后在回溯减去重点等等..但总觉得好像都不太对...赛后才知道这题原来是树的直径.....牡丹江区域现场赛的时候遇到过,不过赛后也没看... 找树的直径的方法其实就是先任取一点进行bfs,找到最远的一点,这时最远的一点肯定是最长链端点之一,然后再从这一最远点开始bf

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

ZOJ Problem Set - 3820 Building Fire Stations 【树的直径 + 操作 】

题目:problemId=5374" target="_blank">ZOJ Problem Set - 3820 Building Fire Stations 题意:给出n个点,n-1条边的一棵树.然后要在两个点上建立两个消防站.让全部点的到消防站最大距离的点的这个距离最小. 分析:首先先求这个树的直径.然后在树的直径的中点处把树分成两棵树.然后在把两棵树分别取中点的最大值就是ans值. 这个题目数据有点水了感觉... AC代码: #include <cstdi

codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relayi

hdu 4607(树的直径)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题解:给定一棵树,从树中的任意选一个顶点出发,遍历K个点的最短距离是多少?(每条边的长度为1) 算法分析: 首先如果k小于等于直径长度,那么答案为k−1;如果k大于直径长度,设直径长度为r,那么答案为r−1+(k−r)*2;树的直径:树上的最长简单路径; 代码: 1 #include <cstdio> 2 #include <cmath> 3 #include <cstri

BZOJ 2282 &amp; 树的直径

SDOI2011的Dayx第2题 题意: 在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在链上的点与这条链的距离最大值最小. SOL: 最大值最小!这不是二分的节奏么?然而hzw学长说二分更直观我却一点都没有体会到... 这道题的关键是猜想(貌似还挺好想)并证明(貌似一直都是可有可无的东西,不过还挺好证的),路径一定在直径上,那么我们先两遍*FS找到直径,用一个队列维护链上的路径,以及预

HDU 4612——Warm up——————【边双连通分量、树的直径】

Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4612 Description N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel bet