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 }

 

 

 

 

只有不断学习才能进步!

 

转载于:https://www.cnblogs.com/wenbao/p/6078872.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值