图论---DFS

1. 图的遍历

在理解DFS算法之前,我们首先需要对什么是遍历进行了解,遍历的概念就是:从某一个点出发(一般是首或尾),依次将数据结构中的每一个数据访问且只访问一遍。

2. DFS简介

DFS(Depth-First-Search,深度优先搜索)算法的具体做法是:从某个点一直往深处走,走到不能往下走之后,就回退到上一步,直到找到解或把所有点走完。

在实现这一个依次的访问顺序时,操作动作存储与数据结构(栈)的思想及其相似,同时也由于栈的性质,我们可以通过递归来简化栈的创建,因此DFS算法的两种做法分别时利用栈或者递归实现。

算法步骤(递归或栈实现)

a)访问指定起始地点。

b)若当前访问顶点的邻接顶点有未被访问的顶点,就任选一个访问。如果没有就回退到最近访问的顶点,直到与起始顶点相通的所有点被遍历完。

c)若途中还有顶点未被访问,则再选一个点作为起始顶点,并重复前面的步骤。

3. 图的DFS

我们直接以案例进行讲解,就本图而言,其访问顺序可以是(不唯一):1-2-4-5-3

首先从1开始,1结点处可以访问2,3两个结点,那么按照我们自定义的优先顺序线访问2结点,此时,2结点有4,5两个结点访问,依旧按次序访问呢4结点,4结点可以访问5结点,5结点无法继续向下访问故结束访问,并回退4结点,4结点无法没有其他分支且自己已被访问故又退回2结点,2结点的两个分支4,5结点均已被访问,故再退回1结点,此时只有3结点未被访问,访问3结点,最终得到次序:1-2-4-5-3

4.相关代码

DFS算法的相关模板如下:

void dfs()//参数用来表示状态
{
if(到达终点状态)
{
...//根据需求添加
return;
}
if(越界或者是不合法状态)
return;
if(特殊状态)//剪枝,去除一些不需要访问的场景,不一定i俺家
return ;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改操作;//根据题意来添加
标记;
dfs();
(还原标记);
//是否还原标记根据题意
//如果加上(还原标记)就是 回溯法
} }
}

5. 图的DFS代码:

#include<iostream>
using namespace std;
#define matrix_size 20
typedef struct {
int weight;
}AdjMatrix[matrix_size][matrix_size]; struct MGraph{
int vex[matrix_size];
AdjMatrix arcs;
int vexnum,arcnum;
};
bool visited[matrix_size]; int LocateVex(MGraph *G ,int v){
int i;
for ( i = 0; i < G->vexnum; i++)
{
if (G->vex[i]==v)
{
break;
}
}
if (i>G->vexnum)
{
cout<<"not such vertex"<<endl;
return -1;
}
return i;
}
//构造无向图
void CreateDN(MGraph *G){
cin>>G->vexnum>>G->arcnum;
for (int i = 0; i < G->vexnum; i++)
{
cin>>G->vex[i];
}
for (int i=0; i<G->vexnum; i++) {
for (int j=0; j<G->vexnum; j++) {
G->arcs[i][j].weight=0;
}
}
for (int i = 0; i < G->arcnum; i++)
{
int v1,v2;
cin>>v1>>v2;
int n=LocateVex(G,v1);
int m=LocateVex(G,v2);
if (m==-1||n==-1)
{
cout<<"not this vertex"<<endl;
return ;
}
G->arcs[n][m].weight=1;
G->arcs[m][n].weight=1;
}
return ;
}
//输出函数
void PrintGrapth(MGraph G)
{
for (int i = 0; i < G.vexnum; i++)
{
for (int j = 0; j < G.vexnum; j++)
{
cout<<G.arcs[i][j].weight<<" ";
}
cout<<endl;
}
}
void visitVex(MGraph G,int v){
cout<<G.vex[v];
}
int FirstAdjVex(MGraph G,int v){
for (int i = 0; i < G.vexnum; i++)
{
//查找与数组下标为v的顶点之间有边的顶点,返回它在数组中的下标
if (G.arcs[v][i].weight)
{
return i;
}
}
return -1;
}
int NextAdjVex(MGraph G,int v,int w)
{
//从前一个访问位置w的下一个位置开始,查找之间有边的顶点
for(int i = w+1; i<G.vexnum; i++){
if(G.arcs[v][i].weight){
return i;
}
}
return -1;
} void DFS(MGraph G,int v){
visited[v]=true;
visitVex(G,v);
for (int w = FirstAdjVex(G,v); w >0; w= NextAdjVex(G,v,w))
{
if (!visited[w])
{
DFS(G,w);
}
}
}
//深度优先搜索
void DFSTraverse(MGraph G){//
int v;
//将用做标记的visit数组初始化为false
for( v = 0; v < G.vexnum; ++v){
visited[v] = false;
}
//对于每个标记为false的顶点调用深度优先搜索函数
for( v = 0; v < G.vexnum; v++){
//如果该顶点的标记位为false,则调用深度优先搜索函数
if(!visited[v]){
DFS( G, v);
}
}
}
int main() {
MGraph G;//建立一个图的变量
CreateDN(&G);//初始化图
DFSTraverse(G);//深度优先搜索图
return 0;
}

图论---DFS的更多相关文章

  1. 【做题】Codeforces Round #436 (Div. 2) F. Cities Excursions——图论+dfs

    题意:给你一个有向图,多次询问从一个点到另一个点字典序最小的路径上第k个点. 考虑枚举每一个点作为汇点(记为i),计算出其他所有点到i的字典序最小的路径.(当然,枚举源点也是可行的) 首先,我们建一张 ...

  2. [LLL邀请赛]参观路线(图论+dfs)

    emmmm....学校的oj被查水表了,扒不到原题面,所以.... 但是我还是扒到了题面... 题目大意:给定一个完全图,删掉其中一些边,然后求其字典序最小的遍历顺序 有点像去年day2T1啊.... ...

  3. 图论--DFS总结

    1.Key word:①双向DFS  ②回溯 今天就看到了这么多DFS,其实DFS更倾向于枚举所有情况. 对于双向DFS,我们考虑看看最短路,起点做一下搜索,记录一下到所有点的距离,终点做一下搜索,记 ...

  4. PJ可能会考的模拟与枚举-自学教程

    PJ可能会考的模拟与枚举-自学教程 文/Pleiades_Antares 之前学校里看一个小可爱复习的时候偷偷听来着XD 简单记了一下重点吧,希望能对看官您有所帮助XD 以下⬇️是几个复习时讲过的题, ...

  5. NOIP提高组历年真题题解

    2018 铺设道路 差分水题,推一下结论就好了. #include<cstdio> #include<algorithm> using namespace std; ],d[] ...

  6. $NOIp$提高组历年题目复习

    写在前面 一个简略的\(NOIp\)题高组历年题目复习记录.大部分都有单独写题解,但懒得放\(link\)了\(QwQ\).对于想的时候兜了圈子的题打上\(*\). \(NOIp2018\ [4/6] ...

  7. 图论算法之DFS与BFS

    概述(总) DFS是算法中图论部分中最基本的算法之一.对于算法入门者而言,这是一个必须掌握的基本算法.它的算法思想可以运用在很多地方,利用它可以解决很多实际问题,但是深入掌握其原理是我们灵活运用它的关 ...

  8. 用深度优先搜索(DFS)解决多数图论问题

    前言 本文大概是作者对图论大部分内容的分析和总结吧,\(\text{OI}\)和语文能力有限,且部分说明和推导可能有错误和不足,希望能指出. 创作本文是为了提供彼此学习交流的机会,也算是作者在忙碌的中 ...

  9. # 「银联初赛第一场」自学图论的码队弟弟(dfs找环+巧解n个二元一次方程)

    「银联初赛第一场」自学图论的码队弟弟(dfs找环+巧解n个二元一次方程) 题链 题意:n条边n个节点的连通图,边权为两个节点的权值之和,没有「自环」或「重边」,给出的图中有且只有一个包括奇数个结点的环 ...

随机推荐

  1. A Python Environment Detector

    The user provide the method to get result(command on remote host), the check standard(a callback fun ...

  2. Send Excerpts from Jenkins Console Output as Email Contents

    Sometimes we need to send some excerpts from Jenkins console output (job logs) as email, such as tes ...

  3. CobaltStrike去除流量特征

    CobaltStrike去除流量特征 ​普通CS没有做流量混淆会被防火墙拦住流量,所以偶尔会看到CS上线了机器但是进行任何操作都没有反应.这里尝试一下做流量混淆.参考网上的文章,大部分是两种方法,一种 ...

  4. 常见web中间件漏洞(二)Apache漏洞

    Apache(总联想到武直那个)是最常见,使用人数最多的一款web服务器软件.跨平台,多扩展,开源,用过的人都说好 Apache的漏洞主要集中在解析漏洞这一块 1.未知扩展名解析漏洞 Apache的一 ...

  5. NOIP 模拟 $38\; \rm a$

    题解 \(by\;zj\varphi\) 压行. 枚举两行,将中间的行压成一行,然后直接前缀和加二分. 注意边界细节问题. Code #include<bits/stdc++.h> #de ...

  6. [转]C# 互操作性入门系列(四):在C# 中调用COM组件

    传送门 C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列(二):使用平台调用调用Win32 函数 C# 互操作性入门系列(三):平台调用中的数据封送处理 ...

  7. DOS创建/删除/描述 windows服务

    1.以管理员运行cmd ,输入 sc create test binPath= 程序路径\xxx.exe,主要 "="后面必须要空格 在服务里面查看结果 2.设置服务格式: sc ...

  8. C#基础知识---匿名方法使用

    一.匿名方法使用 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Tex ...

  9. jsoup的Document类

    一.简介 Document是一个装载html的文档类,它是jsoup一个非常重要的类.类声明:public class Document extends Element .Document是Node间 ...

  10. C#中的信号量---Semaphore

    emaphore是System.Threading下的类,限制可同时访问某一资源或资源池的线程数. 常用构造方法 https://msdn.microsoft.com/zh-cn/library/e1 ...