首页 > 其他分享 >图论-深度优先搜索

图论-深度优先搜索

时间:2024-07-23 09:12:23浏览次数:6  
标签:图论 遍历 int 复杂度 优先 DFS vis 搜索 节点

引入

DFS 全称是 Depth First Search,中文名是深度优先搜索,是一种用于遍历或搜索树或图的算法。所谓深度优先,就是说每次都尝试向更深的节点走。

该算法讲解时常常与 BFS 并列,但两者除了都能遍历图的连通块以外,用途完全不同,很少有能混用两种算法的情况。

DFS 常常用来指代用递归函数实现的搜索,但实际上两者并不一样。有关该类搜索思想请参阅 DFS(搜索).

过程

DFS 最显著的特征在于其 递归调用自身。同时与 BFS 类似,DFS 会对其访问过的点打上访问标记,在遍历图时跳过已打过标记的点,以确保 每个点仅访问一次。符合以上两条规则的函数,便是广义上的 DFS。

具体地说,DFS 大致结构如下:

DFS(v) // v 可以是图中的一个顶点,也可以是抽象的概念,如 dp 状态等。
  在 v 上打访问标记
  for u in v 的相邻节点
    if u 没有打过访问标记 then
      DFS(u)
    end
  end
end

以上代码只包含了 DFS 必需的主要结构。实际的 DFS 会在以上代码基础上加入一些代码,利用 DFS 性质进行其他操作。

性质

该算法通常的时间复杂度为 O(n+m),空间复杂度为 O(n),其中 n 表示点数,m 表示边数。注意空间复杂度包含了栈空间,栈空间的空间复杂度是 O(n) 的。在平均 O(1) 遍历一条边的条件下才能达到此时间复杂度,例如用前向星或邻接表存储图;如果用邻接矩阵则不一定能达到此复杂度。

备注:目前大部分算法竞赛(包括 NOIP、大部分省选以及 CCF 举办的各项赛事)都支持 无限栈空间,即:栈空间不单独限制,但总内存空间仍然受题面限制。但大部分操作系统会对栈空间做额外的限制,因此在本地调试时需要一些方式来取消栈空间限制。

在 Windows 上,通常的方法是在 编译选项 中加入 -Wl,--stack=1000000000,表示将栈空间限制设置为 1000000000 字节。
在 Linux 上,通常的方法是在运行程序前 在终端内 执行 ulimit -s unlimited,表示栈空间无限。每个终端只需执行一次,对之后每次程序运行都有效。

实现

栈实现
DFS 可以使用 栈(Stack) 为遍历中节点的暂存容器来实现;这与用 队列(Queue) 实现的 BFS 形成高度对应。

vector<vector<int>> adj;  // 邻接表
vector<bool> vis;         // 记录节点是否已经遍历

void dfs(int s) {
  stack<int> st;
  st.push(s);
  vis[s] = true;

  while (!st.empty()) {
    int u = st.top();
    st.pop();

    for (int v : adj[u]) {
      if (!vis[v]) {
        vis[v] = true;  // 确保栈里没有重复元素
        st.push(v);
      }
    }
  }
}

递归实现

函数在递归调用时的求值如同对栈的添加和删除元素的顺序,故函数调用所占据的虚拟地址被称为函数调用栈(Call Stack),DFS 可用递归的方式实现。

以 邻接表(Adjacency List) 作为图的存储方式:

vector<vector<int>> adj;  // 邻接表
vector<bool> vis;         // 记录节点是否已经遍历

void dfs(const int u) {
  vis[u] = true;
  for (int v : adj[u])
    if (!vis[v]) dfs(v)
}

以 链式前向星 为例:

void dfs(int u) {
  vis[u] = 1;
  for (int i = head[u]; i; i = e[i].x) {
    if (!vis[e[i].t]) {
      dfs(v);
    }
  }
}

DFS 序列

DFS 序列是指 DFS 调用过程中访问的节点编号的序列。

我们发现,每个子树都对应 DFS 序列中的连续一段(一段区间)。

括号序列

DFS 进入某个节点的时候记录一个左括号 (,退出某个节点的时候记录一个右括号 )。

每个节点会出现两次。相邻两个节点的深度相差 1。

一般图上 DFS

对于非连通图,只能访问到起点所在的连通分量。

对于连通图,DFS 序列通常不唯一。

注:树的 DFS 序列也是不唯一的。

在 DFS 过程中,通过记录每个节点从哪个点访问而来,可以建立一个树结构,称为 DFS 树。DFS 树是原图的一个生成树。

DFS 树 有很多性质,比如可以用来求强连通分量。

标签:图论,遍历,int,复杂度,优先,DFS,vis,搜索,节点
From: https://www.cnblogs.com/mcr130102/p/18317492

相关文章

  • spring使用mysql数据库实现关键字别字、拼音、拼音首字母、拼音所有首字母组合搜索
    1、实现思路前端传入的文字、拼音、别字、拼音首字母、拼音所有首字母组合传入到后台,通过后台接口转成拼音,然后通过转换后的拼音结合sql语句查询匹配。2、后台实现pom配置:<!--中文转拼音--><dependency><groupId>com.belerweb</groupId><artifactId>pinyin4......
  • 如何使用 Selenium Python 搜索 Excel 文件中的文本
    我有一些数据在Excel文件中。我想要转到Excel文件,然后搜索文本(取自网站表),然后获取该行的所有数据,这些数据将用于在浏览器中填充表格。示例:我希望selenium搜索ST0003然后获取名称,该学生ID的父亲姓名,以便我可以在大学网站中填写此信息。我想我会从网站......
  • 《搜索型数据库白皮书》正式发布,极限科技荣登贡献单位榜单
    7月17日下午,在“2024可信数据库发展大会”搜索与分析型数据库&多模数据库分论坛上,中国通信标准化协会大数据技术标准推进委员会(以下简称:CCSATC601)正式发布了《搜索型数据库白皮书》。此次白皮书的编制工作由中国信通院云计算与大数据研究所牵头,联合包括极限科技在内的多家......
  • Elastic 及阿里云 AI 搜索 Tech Day 将于 7 月 27 日在上海举办
    活动主题面向开发者的AI搜索相关技术分享,如RAG、多模态搜索、向量检索等。活动介绍参加Elastic原厂与阿里云联合举办的Generative AI技术交流分享日。借助The Elastic Search AI Platform, 使用开放且灵活的企业解决方案,以前所未有的速度获得搜索最相关的结......
  • 2024年最新AI大模型,一文带你走进AI搜索!
    在这个知识泛滥的时代,AI搜索成为了我们获取知识的利器。只需输入几个关键词,AI搜索就能洞察你的需求,不仅提供精确答案,还能生成脑图、PPT,甚至专题分析文章!然而在信息爆炸的时代,AI搜索就像是一把淘金铲,帮助我们筛选出有价值的信息。就像鲁迅先生所说:“输入的是垃圾,输出的也是......
  • 代码随想录算法训练营第17天 | 复习二叉搜索树
    2024年7月19日题654.最大二叉树熟练运用递归即可classSolution{publicTreeNodeconstructMaximumBinaryTree(int[]nums){intmaxNum=Integer.MIN_VALUE;intflag=-1;for(inti=0;i<nums.length;i++){if(nums[i]>maxNum){......
  • 【保姆级讲解C语言中的运算符的优先级!】
    ......
  • 在K8S中,优先优选哪个CNI插件?为何使用该插件?
    在Kubernetes(K8s)中,选择哪个CNI(ContainerNetworkInterface)插件并没有绝对的“最优”选择,因为不同的插件适用于不同的场景和需求。以下是一些常见的CNI插件及其特点,以及选择它们时可能考虑的因素:1.Flannel特点:最常用的K8s网络插件之一。使用虚拟网络技术(如VXLAN、UDP和Host-......
  • 【搜索】【模板】 IDDFS
    IDDFS使用场景使用dfs由于状态量太大会TLE,bfs会MLE。答案必须很小,一般在20以内。算法原理设置dfs的搜索深度限制\(dep\),dfs穷举\(dep\)层的答案。若在\(dep\)层找到满足条件的情形,则\(dep\)则为答案,否则\(dep\leftarrowdep+1\),继续搜索。优......
  • 【搜索】【模板】记忆化搜索
    记忆化搜索思想是实现DP的一种手段。优点:不关心递推顺序;对于两维及以上的DP,方便处理初始状态和无效状态。缺点:无法使用滚动数组。注意事项:要什么状态搜什么状态;所有的状态转移都要采取直接搜索的数据很傻。越界的状态不能赋值。实现步骤:先判断是否越界,如果越......