• 5.树的重心 树与图的深度优先遍历


     

     树和图有两种存储方式,树是一种特殊的图,树是无环连通图

    图分为有向图和无向图,无向图是一种特殊的有向图

     所以就只需要考虑有向图怎样存储

    有向图的存储有两大类

    第一大类是用得比较少的邻接矩阵,就是开个二维数组g[a][b]存储a到b这条边的信息,这条边有权重就记录权重,没权重就记录这条边是否存在,0或1

      邻接矩阵是不能存储重边的,只能存储一条(权重最小)的边

      领接矩阵比较浪费空间,空间复杂度n ^ 2,适合存储稠密图

    第二大类是用得最多的邻接表

      邻接表就是之前的单链表。如果有n个点的话,就开n个单链表。

      和拉链法的哈希表一样

      每个点上的单链表存储这个点可以到哪个点去

      举个例子

      比如有一个这样的图

      

       然后如何用单链表存储上面这个图呢

      因为有4个点,所以就开4个单链表

      单链表内部每个点的次序无所谓

      

       当想插入一条新的边时

      

       先找到2这个点对应的单链表,然后把3插到里面去,一般用头插法

      h[i]表示第i个点的头

      

     树和图的遍历有两种方式,深度优先遍历和宽度优先遍历

     这个图的深度优先遍历是这样

     宽度优先遍历是这样

     注意一点,深度优先遍历和宽度优先遍历每一个点都只会遍历一次

    树和图的深搜

     深度优先遍历可以算出来每一个子树中的点的数量

    树和图的深度优先遍历和宽度优先遍历时间复杂度都是O(n + m)的,n是点,m是边

    不一定非要从1开始搜,从哪个点开始都是一样的

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 100010, M = 2 * N;
     4 int n;
     5 int h[N], e[M], ne[M], idx;
     6 //h[]数组存的是n个链表的链表头
     7 //e[]数组存每一个节点的值是多少
     8 //ne[]数组存每一个节点能next指针
     9 bool st[N]; //存储哪些点已经遍历过了
    10 int ans = N;
    11 void add(int a, int b) { //插入一条a指向b的边
    12     //在a对应的邻接表里插入一个节点b
    13     e[idx] = b;
    14     ne[idx] = h[a];
    15     h[a] = idx;
    16     idx++;
    17 }
    18 //返回以u为根的子树的大小
    19 int dfs(int u) { //u是当前已经遍历到的点
    20     st[u] = true; //标记一下,当前这个点已经被搜过了
    21     int sum = 1; //sum是当前这个子树的大小
    22     int res = 0; //res是把这个点删除之后,剩下的每一个连通块的大小的最大值
    23     for (int i = h[u]; i != -1; i = ne[i]) { //遍历一下u的所有出边
    24         int j = e[i]; //当前这个链表里的节点对应于图中点的编号
    25         if (!st[j]) {
    26             int s = dfs(j); //s表示当前这个子树的大小
    27             res = max(res, s); //当前这个子树也算是连通块
    28             sum += s; //以这个儿子为根节点的子树是以u为根节点子树的一部分
    29         }
    30     }
    31     //n - sum是上面连通块的数量
    32     res = max(res, n - sum);
    33     ans = min(ans, res);
    34     return sum;
    35 }
    36 int main() {
    37     cin >> n;
    38     memset(h, -1, sizeof(h));
    39     for (int i = 0; i < n - 1; i++) {
    40         int a, b;
    41         cin >> a >> b;
    42         add(a, b);
    43         add(b, a);
    44     }
    45     dfs(1); //从第一个点开始搜
    46     cout << ans << endl;
    47     return 0;
    48 }
  • 相关阅读:
    Kubernetes笔记 (2)
    Kubernetes笔记(3)
    Kubernetes笔记 (1)
    《深入浅出React和Redux》(4)
    【从0安装】xshell和xftp
    【从0安装】Sourcetree
    postman测试需要登录的接口
    vue自定义滚动条组件-vuebar组件
    charles 抓包http 和 https
    pycharm 面板颜色调整和中文汉化
  • 原文地址:https://www.cnblogs.com/fx1998/p/13324351.html
Copyright © 2020-2023  润新知