wenbao与树的直径
1. 树上面求最长路简单路(无环). 就是树的直径问题.
2. 树的直径问题经典: 两遍BFS即可.
问题分析:
(1). 一开始任取一个点u进行搜索查找出距离点u最远距离的点v和长度.
(2). 第二次BFS则从第一次中的点v找出距离点v最远距离的点的路径长度.
3. 问题正确性.
证明:
(1). 情况1: u在最长路上, 那么v一定是最长路的一端.
反证法: v不是在最长路的一端, 即有一个v1使得(u->v1)是最长路的一部分, 就有: dist(u->v1) > dist(u->v); 矛盾.
即: v在最长路的一端. (第二次BFS就可以找出距离v最远的点的长度.)
(2). 情况2: u不再最长路上, 则有点u到点v的路与最长路一定有一个交点c.
并且(c->v)与最长路的后半段是重合的. 即v一定是最长路的一端.
1 int dis = -1, node; 2 void dfs(int x, int num){ 3 if(num > dis){ 4 dis = num, node = x; 5 } 6 for(int i = 0; i < v[x].size(); i++){ 7 dfs(v[x][i], num+1); 8 } 9 } 10 dfs(1, 1); 11 dis = -1; 12 dfs(node, 1); 13 dis == 直径
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
http://lx.lanqiao.cn/problem.page?gpid=T32
裸的树的直径
1 #include <iostream> 2 #include <vector> 3 #include <queue> 4 #include <string.h> 5 using namespace std; 6 const int maxn = 1e4+10; 7 vector<int> v[maxn]; 8 vector<int> vv[maxn]; 9 bool vis[maxn]; 10 int n, sum, u; 11 struct Node{ 12 int vu, num; 13 }; 14 void d(int x){ 15 memset(vis, false, sizeof(vis)); 16 Node a, b; 17 queue<Node> q; 18 a.vu = 0, a.num = x; 19 q.push(a); 20 vis[x] = true; 21 while(!q.empty()){ 22 b = q.front(); 23 q.pop(); 24 int xx = b.num, vul = b.vu; 25 for(int i = 0; i < v[xx].size(); ++i){ 26 int xxx = v[xx][i]; 27 if(!vis[xxx]){ 28 vis[xxx] = true; 29 a.vu = vul + vv[xx][i], a.num = xxx; 30 if(a.vu > sum){ 31 sum = a.vu; 32 u = xxx; 33 } 34 q.push(a); 35 } 36 } 37 } 38 } 39 using namespace std; 40 int main(){ 41 int x, y, z; 42 scanf("%d", &n); 43 for(int i = 1; i < n; ++i){ 44 scanf("%d%d%d", &x, &y, &z); 45 v[x].push_back(y), v[y].push_back(x); 46 vv[x].push_back(z), vv[y].push_back(z); 47 } 48 d(1); 49 d(u); 50 printf("%d\n", (21+sum)*sum/2); 51 return 0; 52 }
只有不断学习才能进步!