• 树和图的深度与广度优先遍历(树的重心,图中点的层次)


    846. 树的重心

    给定一颗树,树中包含 n

    个结点(编号 1∼n)和 n−1

    条无向边。

    请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

    重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

    输入格式

    第一行包含整数 n

    ,表示树的结点数。

    接下来 n−1

    行,每行包含两个整数 a 和 b,表示点 a 和点 b

    之间存在一条边。

    输出格式

    输出一个整数 m

    ,表示将重心删除后,剩余各个连通块中点数的最大值。

    数据范围

    1≤n≤105

    输入样例

    1. 9
    2. 1 2
    3. 1 7
    4. 1 4
    5. 2 8
    6. 2 5
    7. 4 3
    8. 3 9
    9. 4 6

    输出样例:

    4
    

    /**
     * 重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中
     * 点数的最大值最小,那么这个节点被称为树的重心。
     *
     * 由于是树,所以该图一定是连通的,那么求出每一个节点的最大子树的节点个数,
     * n个结点相比,得到最小的值就是答案。
     *
     * for(int i=0;i     {
            int v=Adj[u][i];
            if(hs[v]==0)
            {
                hs[v]=1;
                int j=dfs(v);
                sum+=j;  //累加子树的节点数
                ans=max(ans,j); //计算子树的最大节点数
                // hs[v]=0; //为什么这儿不需要回溯,是因为这是树,u的子节点
                //v1被访问了,那么u的子节点 v2 及v2 的子孙结点都不可能与v1
                //有边相连,否则就会出现回路;其实更准确的解释是树的每个节点
                //都只会被访问一次
            }
        }
    */

    1. /**
    2. * 重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中
    3. * 点数的最大值最小,那么这个节点被称为树的重心。
    4. *
    5. * 由于是树,所以该图一定是连通的,那么求出每一个节点的最大子树的节点个数,
    6. * n个结点相比,得到最小的值就是答案。
    7. *
    8. * for(int i=0;i
    9. {
    10. int v=Adj[u][i];
    11. if(hs[v]==0)
    12. {
    13. hs[v]=1;
    14. int j=dfs(v);
    15. sum+=j; //累加子树的节点数
    16. ans=max(ans,j); //计算子树的最大节点数
    17. // hs[v]=0; //为什么这儿不需要回溯,是因为这是树,u的子节点
    18. //v1被访问了,那么u的子节点 v2 及v2 的子孙结点都不可能与v1
    19. //有边相连,否则就会出现回路;其实更准确的解释是树的每个节点
    20. //都只会被访问一次
    21. }
    22. }
    23. */
    24. /**
    25. #include <iostream>
    26. #include <algorithm>
    27. #include <vector>
    28. using namespace std;
    29. const int N = 1e5+10; // 最大边数
    30. vector<int> Adj[N]; //邻接表
    31. bool hs[N]; //顶点是否被访问
    32. int res = N; //结果
    33. int n; //顶点数
    34. void Read() // 读入数据
    35. {
    36. cin >> n;
    37. for(int i=1;i<n;++i)
    38. {
    39. int u,v;
    40. cin >> u >> v;
    41. Adj[u].push_back(v);
    42. Adj[v].push_back(u);
    43. }
    44. }
    45. int dfs(int u) //返回以u为根的所有子树的节点数(包括结点u)
    46. {
    47. hs[u]=1;
    48. int sum=1,ans=0; //sum 记录以u为根的所有子树的的节点数,ans记录最大的子树的节点数
    49. for(int i=0;i<Adj[u].size();++i)
    50. {
    51. int v=Adj[u][i];
    52. if(hs[v]==0)
    53. {
    54. int j=dfs(v);
    55. sum+=j; //累加子树的节点数
    56. ans=max(ans,j); //计算子树的最大节点数
    57. }
    58. }
    59. ans=max(ans,n-sum); //计算与u相连的连通块中最大的节点数
    60. res=min(res,ans); //计算结果,各个节点的连通块中节点数中最大值中的最小值
    61. return sum;
    62. }
    63. int main()
    64. {
    65. Read();
    66. dfs(1);
    67. cout << res << endl;
    68. return 0;
    69. }
    70. */

    847. 图中点的层次

    给定一个 n

    个点 m

    条边的有向图,图中可能存在重边和自环。

    所有边的长度都是 1

    ,点的编号为 1∼n

    请你求出 1

    号点到 n 号点的最短距离,如果从 1 号点无法走到 n 号点,输出 −1

    输入格式

    第一行包含两个整数 n

    和 m

    接下来 m

    行,每行包含两个整数 a 和 b,表示存在一条从 a 走到 b 的长度为 1

    的边。

    输出格式

    输出一个整数,表示 1

    号点到 n

    号点的最短距离。

    数据范围

    1≤n,m≤105

    输入样例:

    1. 4 5
    2. 1 2
    3. 2 3
    4. 3 4
    5. 1 3
    6. 1 4

    输出样例:

    1
    

    这个题就和走迷宫所需步数的问法一摸一样:

     解法一:

    1. #include <iostream>
    2. #include <algorithm>
    3. #include <queue>
    4. using namespace std;
    5. const int maxn = 1e5+10;
    6. vector<int> Adj[maxn];
    7. int d[maxn];
    8. int n,m;
    9. void Read()
    10. {
    11. cin >> n >> m;
    12. for(int i=0;i<m;++i)
    13. {
    14. int u,v;
    15. cin >> u >> v;
    16. Adj[u].push_back(v);
    17. }
    18. }
    19. int bfs(int st)
    20. {
    21. queue<int> q;
    22. q.push(st);
    23. d[st]=0;
    24. while(q.size())
    25. {
    26. int u=q.front();
    27. q.pop();
    28. if(u==n)
    29. return d[n];
    30. for(int i=0;i<Adj[u].size();++i)
    31. {
    32. int v=Adj[u][i];
    33. if(u!=v && d[v]==0) //必须判断u是否等于v,即判断是否为自环
    34. {
    35. q.push(v);
    36. d[v]=d[u]+1;
    37. }
    38. }
    39. }
    40. return -1;
    41. }
    42. int main()
    43. {
    44. Read();
    45. cout << bfs(1) << endl;
    46. return 0;
    47. }

    解法二:堆优化的Dijkstra算法,将每一条边看成权值为1的有向边;

    1. #include <iostream>
    2. #include <algorithm>
    3. #include <queue>
    4. using namespace std;
    5. const int maxn = 1e5+10;
    6. vector<int> Adj[maxn];
    7. int d[maxn];
    8. int n,m;
    9. void Read()
    10. {
    11. cin >> n >> m;
    12. for(int i=0;i<m;++i)
    13. {
    14. int u,v;
    15. cin >> u >> v;
    16. Adj[u].push_back(v);
    17. }
    18. }
    19. int bfs(int st)
    20. {
    21. queue<int> q;
    22. q.push(st);
    23. d[st]=0;
    24. while(q.size())
    25. {
    26. int u=q.front();
    27. q.pop();
    28. if(u==n)
    29. return d[n];
    30. for(int i=0;i<Adj[u].size();++i)
    31. {
    32. int v=Adj[u][i];
    33. if(u!=v && d[v]==0) //必须判断u是否等于v,即判断是否为自环
    34. {
    35. q.push(v);
    36. d[v]=d[u]+1;
    37. }
    38. }
    39. }
    40. return -1;
    41. }
    42. int main()
    43. {
    44. Read();
    45. cout << bfs(1) << endl;
    46. return 0;
    47. }

  • 相关阅读:
    异步编程:CompletableFuture详解使用
    json数组能不能放到hashmap中
    【源码分析】Spring的循环依赖(setter注入、构造器注入、多例、AOP)
    世界前沿技术发展报告2023《世界航天技术发展报告》(五)太空探索技术
    TCP重头戏来!了!(2) —— 小林图解学习摘记
    【AutoSAR CAN】02 - 硬件过滤器配置
    Linux权限
    java计算机毕业设计技术旅游平台(附源码、数据库)
    SpringBoot - Identify and stop the process that‘s listening on port 8080解决方案
    Java基础:Java数据类型
  • 原文地址:https://blog.csdn.net/qq_51825761/article/details/126743067