• 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
    ", (21+sum)*sum/2);
    51     return 0;
    52 }

    只有不断学习才能进步!

  • 相关阅读:
    自定义类似MessageBox小窗体操作
    WinForm 遍历用户控件里CheckBox
    WinForm BaseClass类常用通用方法
    分页的几种写法
    克服粗心毛病的伪代码
    C++queue的使用
    Unix网络编程学习 < 一 >
    使用log4cxx
    memset函数
    libcurl在windows下的使用
  • 原文地址:https://www.cnblogs.com/wenbao/p/6078872.html
Copyright © 2020-2023  润新知