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。