• 树的dfs和bfs


    树的重心

    给定一颗树,树中包含 nn 个结点(编号 1∼n1∼n)和 n−1n−1 条无向边。

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

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

    输入格式

    第一行包含整数 nn,表示树的结点数。

    接下来 n−1n−1 行,每行包含两个整数 aa 和 bb,表示点 aa 和点 bb 之间存在一条边。

    输出格式

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

    数据范围

    1≤n≤1051≤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

    该题是无向图,稀疏图,我们采用临接表的形式来进行存储, 类似于单链表的存储方式。

    首先对h 处理成-1。

    然后是add操作,也就是对两个点进行连边,由于我们是无向图,也就是说我们需要两边各连一次,重复两次add操作。

    int dfs(int u)
    {
        st[u] = true;
        for (int i = h[u]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (st[j]) continue; //访问过就跳过

            dfs(j); 
        }
    }

    然后具体到这道题目就是不同的dfs,返回的数据类型等。

    1. #include<iostream>
    2. #include<cstring>
    3. #include<cstdio>
    4. #include<algorithm>
    5. using namespace std;
    6. const int N=100010,M=N*2;
    7. int n;
    8. int h[N],e[M],ne[M],idx;
    9. int ans=N;
    10. bool vis[N];
    11. void add(int a,int b){ //建图,链式前向星
    12. e[idx]=b;ne[idx]=h[a];h[a]=idx++;
    13. }
    14. int dfs(int u){
    15. vis[u]=1; //标记走过
    16. int size=0,sum=0; //前者为存删除u点后,最大的连通子图节点数,后者为以u为根的节点数(用来求该点上面连通块的点数的)
    17. for(int i=h[u];i!=-1;i=ne[i]){ //深搜
    18. int j=e[i];
    19. if(vis[j]) continue; //如果走过,那就不用管
    20. int s=dfs(j); //s为u点下面以j为结点的连通块的点数
    21. size=max(size,s); // 这是在求u点之下连通块的点数,来找一个最大值
    22. sum+=s;
    23. }
    24. size=max(size,n-sum-1); //与u点上面连通块的点数,取个最大值
    25. ans=min(ans,size); //这是求答案,根据题目,求删掉各个点后,最小的最大连通块点数
    26. return sum+1;
    27. }
    28. int main(){
    29. scanf("%d",&n);
    30. memset(h,-1,sizeof(h));
    31. for(int i=0;i<n-1;i++){
    32. int a,b;
    33. scanf("%d%d",&a,&b);
    34. add(a,b),add(b,a);
    35. }
    36. dfs(1);
    37. printf("%d\n",ans);
    38. return 0;
    39. }
    40. //Wraith_G

    这里引用一下 Wraith_G 的代码,很感谢!因为我的注释写的不清楚。。

    对于bfs:

    图中点的层次:

    给定一个 nn 个点 mm 条边的有向图,图中可能存在重边和自环。

    所有边的长度都是 11,点的编号为 1∼n1∼n。

    请你求出 11 号点到 nn 号点的最短距离,如果从 11 号点无法走到 nn 号点,输出 −1−1。

    输入格式

    第一行包含两个整数 nn 和 mm。

    接下来 mm 行,每行包含两个整数 aa 和 bb,表示存在一条从 aa 走到 bb 的长度为 11 的边。

    输出格式

    输出一个整数,表示 11 号点到 nn 号点的最短距离。

    数据范围

    1≤n,m≤1051≤n,m≤105

    输入样例:

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

    输出样例:

    1

    这道题目,像是低配版的dijkstra,由于边的长度为1, 并且存在重边和自环,输出的是1到n的距离,更形象的说n是1节点的第几层根。

     然后就可以写了,用bfs,不断地插入,取出数据,然后用图的遍历来进行判断,符合要求的押入队列。

    1. #include <iostream>
    2. #include <cstring>
    3. #include <queue>
    4. using namespace std;
    5. const int N = 1e05 + 10, M = N * 2;
    6. int read(){
    7. int res = 0 , flag = 1 ;
    8. char c = getchar() ;
    9. while(!isdigit(c)){
    10. if(c == '-') flag = -1 ;
    11. c = getchar() ;
    12. }
    13. while(isdigit(c)){
    14. res = (res << 1) + (res << 3) + (c ^ 48) ;
    15. c = getchar() ;
    16. }
    17. return res * flag ;
    18. }
    19. int e[N], ne[N], h[N], idx;
    20. int d[N];
    21. void add(int a, int b) {
    22. e[idx] = b;
    23. ne[idx] = h[a];
    24. h[a] = idx ++;
    25. }
    26. int n, m;
    27. int bfs() {
    28. queue<int> q;
    29. q.push(1);
    30. memset(d, -1, sizeof d);
    31. d[1] = 0;
    32. while (q.size()) {
    33. auto u = q.front();
    34. q.pop();
    35. for (int i = h[u]; i != -1; i = ne[i]) {
    36. int t = e[i];
    37. if (d[t] == -1) { //没有被访问过
    38. d[t] = d[u] + 1; //
    39. q.push(t);
    40. }
    41. }
    42. }
    43. return d[n];
    44. }
    45. int main() {
    46. memset(h, -1, sizeof h);
    47. n = read();
    48. m = read();
    49. for (int i = 0; i < m; i++) {
    50. int a, b;
    51. a = read();
    52. b = read();
    53. add(a, b);
    54. }
    55. cout << bfs();
    56. return 0;
    57. }

  • 相关阅读:
    shell 多线程
    QT使用QThread创建线程的方法
    2023最新接口自动化测试面试题
    计算器中处于不同进制时
    Python 全栈打造某宝客微信机器人
    IDEA 本地远程执行MapReduce(HA集群)程序找不到自定义Mapper与Reduce类
    跟李沐学AI-深度学习课程04数据操作
    六级高频词汇
    [送给她]最近比较火的给她推送天气,恋爱倒计时等功能教程
    Kali Linux 安装使用远程桌面连接远程服务器
  • 原文地址:https://blog.csdn.net/beloved_yu/article/details/125525033