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。

原文地址:https://www.cnblogs.com/fangziyuan/p/6980328.html