图论--DFS搜索图/树

打印 上一主题 下一主题

主题 1763|帖子 1763|积分 5289

目录
一、图的存储结构
二、题目练习
846. 树的重心 - AcWing题
           dfs,之前学习的回溯算法好多都是用dfs实现搜索的(把题目抽象成树形结构来搜索),实在 回溯算法就是 深搜,只不过针对某一搜索场景 我们给他一个更细分的定义,叫做回溯算法
  本节专门解说dfs在图上的应用,需要做的就是① 明白图的存储结构(毗邻矩阵、毗邻表),② 背模版 ③  刷题 
  一、图的存储结构

看这篇博文就OK
图的存储方式总结:如何高效表示顶点与边的关系?-CSDN博客
最复杂的写法也就是 vector<vector<pair<int, int>>> g  ,虽然看起来复杂,但是比力好理解,这里我是跟着卡哥学习的写法,之前yxc大佬的数组写法呜呜呜我真的只能一时理解不能恒久记忆,也写过相关博客条记 ACWing【846】树的重心、图中点的层次 、毗邻表存储图/树、dfs/bfs搜索图/树_图中点的层次acwing-CSDN博客
其时写完应该是明白的,但是现在看真的一头雾水。。。。。
二、题目练习

        之前细致学过的部分,这里温习一下就好啦,看这篇博客 ,里面有四道经典例题(那很经典了)深度优先搜索DFS-从入门到醒目【卡玛】_
   所有可达路径属于---模版题,搜索1--n的所有路径并输出
  
  岛屿问题用来练习网格连通块识别问题
  

  • 岛屿数量-----统计有多少个由“1”组成的互不连通区域,连通快计数问题
  • 岛屿最大面积---找最大的连通块
  • 沉默孤岛和孤岛总面积属于-------连通块/连通域标记题型
  博客中有四道经典例题~回顾之后下面再练习几道新题
   明白用什么存储图
  图是有向边吗照旧无向边? 会有重边吗?需要利用visited数组吗??搜索的时间注意边界?
  树的重心问题 ,如何操作树结构(实在和图没什么差别)
846. 树的重心 - AcWing题库


    树的重心问题,挺简单的一道题,重要是理解题意,什么是最大节点数最小???
  这里我们利用 DFS 统计每个节点删除后各子树巨细的最大值,然后取所有节点中这个“最大值”的最小值
  

  

  思路:
  1. 1. 从根节点开始DFS
  2. 2. 递归计算每个节点的所有子树规模
  3. 3. 在回溯时计算:
  4.    - 子节点方向的最大连通块
  5.    - 父节点方向的剩余连通块
  6. 4. 比较并更新全局最小值
  7. 5. 最终输出所有可能分割方案中的最优解
复制代码
搞清子节点和父节点!!!!很关键
  子节点的巨细盘算如下图:
  

  父节点就是n-累加的所有子节点数啦
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + 10;      // 最大节点数
  4. vector<int> edges[N];        // 邻接表存储树结构
  5. int n;                       // 节点总数
  6. int min_max = INT_MAX;       // 存储最小的最大连通块大小(初始化为极大值)
  7. /**
  8. * 深度优先搜索计算子树信息
  9. * @param u      当前节点
  10. * @param parent 父节点(用于防止回溯)
  11. * @return 以u为根的子树节点数
  12. */
  13. int dfs(int u, int parent) {
  14.     int subtree_size = 1;    // 当前子树节点数(至少包含自己)
  15.     int max_part = 0;        // 删除u后最大的连通块大小
  16.     // 遍历所有邻接节点(包含父节点和子节点)
  17.     for (int v : edges[u]) {
  18.         if (v == parent) continue; // 跳过父节点防止回溯
  19.         // 递归获取子树的节点数(此时u是v的父节点)
  20.         int child_size = dfs(v, u);
  21.         max_part = max(max_part, child_size); // 更新子节点方向的最大块
  22.         subtree_size += child_size;    // 累加子树规模,用于计算父节点数目
  23.     }
  24.         
  25.     // 子节点的最大块为max_part 父节点方向的连通块大小 = 总节点数 - 当前子树规模
  26.     max_part = max(max_part, n - subtree_size);
  27.    
  28.     // 全局维护最小值(所有节点的最大连通块中的最小值)
  29.     min_max = min(min_max, max_part);
  30.     return subtree_size; // 返回当前子树的规模(给上层递归使用)
  31. }
  32. int main() {
  33.     // 加速输入输出(处理大规模数据时效果显著)
  34.     ios::sync_with_stdio(false);
  35.     cin.tie(nullptr);
  36.     cin >> n;
  37.    
  38.     // 构建树结构(n-1条边)
  39.     for (int i = 0; i < n-1; ++i) {
  40.         int a, b;
  41.         cin >> a >> b;
  42.         edges[a].push_back(b); // 无向图双向连接
  43.         edges[b].push_back(a);
  44.     }
  45.     dfs(1, -1); // 从任意节点开始遍历(根节点设为1,父节点不存在用-1表示)
  46.     cout << min_max << endl;
  47.     return 0;
  48. }
复制代码




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

络腮胡菲菲

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表