DFS应用——遍历有向图+判断有向图是否有圈
【0】README
0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 “DFS应用——遍历有向图+判断有向图是否有圈” 的idea 并用源代码加以实现 ;
0.2) 判断有向图是否有圈的rule—— 一个有向图是无圈图当且仅当它没有背向边,背向边定义,参见: http://blog.csdn.net/pacosonswjtu/article/details/49967255
0.3) ** 代码最后还添加了打印dfs遍历路径所产生的集合, 对的,dfs 就应该这么玩**,Bingo!
【1】有向图相关
1.1)对有向图进行DFS的idea:利用与无向图相同的思路, 也可以通过深度优先搜索以线性时间遍历有向图。如果图不是强连通的,那么从某个节点开始的DFS可能访问不了所有的节点。在这种情况下, 我们在某个未作标记的节点处开始,反复执行DFS, 直到所有节点都被访问到;
1.2)基于以上描述, 我们看个荔枝(这只是一种可能的case):
- step1)从顶点B 任意开始深度优先搜索, 访问顶点B, C, A, D, E;
- step2)从顶点 F 任意开始DFS, 访问顶点 F;
- step3)从顶点 H 任意开始DFS, 访问顶点 H, J, I;
- step4)从顶点 G 任意开始DFS, 访问顶点 G;
1.3)对于以上的DFS过程, 对应的搜索优先搜索树如下图所示:
对上图的分析(Analysis):
- A1)深度优先生成森林中虚线箭头是一些(v, w)边, 其中的w 在考察时已经做了标记;
- A2)我们看到,存在三种类型的边并不通向新顶点:
- A2.1)背向边:如(A,B) 和 (I,H);
- A2.2)前向边:如(C,D) 和 (C,E), 它们从树的一个节点通向一个后裔;
- A2.3)交叉边:如(F,C)和(G,F), 它们把不直接相关的两个树节点连接起来;
- A3)深度优先搜索森林一般通过吧一些子节点和一些新的树从左到右添加到森林中形成。 在以这种方式构成的有向图的深度优先搜索中,交叉边总是从右到左进行的;
1.4)深度优先搜索(DFS)的一个用途是: 检测一个有向图是否是无圈图;
- 4.1) 法则如下: 一个有向图是无圈图当且仅当它没有背向边;(上面的图有背向边, 因此它不是无圈图)
- 4.2)拓扑排序也可以用来确定一个图是否是无圈图。进行拓扑排序的另一种方法是通过深度优先生成森林的后序遍历给顶点指定拓扑编号N, N-1, ..., 1; 只要图是无圈的,这种排序就是一致的;
【2】source code + printing results(此处的dfs是对原始dfs修改而成的,与原始的dfs不同,但idea一样)
2.1)download source code: https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter9/p248_dfs_directed_graph
2.2)source code at a glance:(for complete code , please click the given link above)
void dfs(Vertex vertex, int depth)
{
int i;
int visitFlag;
AdjTable temp;
Vertex adjVertex;
//printf("\n\t visited[%c] = 1 ", flag[vertex]);
visited[vertex] = 1; // update visited status of vertex
vertexIndex[vertex] = counter++; // number the vertex with counter
temp = adj[vertex];
visitFlag = 0;
while(temp->next)
{
adjVertex = temp->next->vertex;
if(visited[adjVertex]) // judge whether the adjVertes was visited before
{
if(vertexIndex[vertex] > vertexIndex[adjVertex] && parent[vertex] != adjVertex)
{
parent[adjVertex] = vertex; // building back side, attention of condition of building back side above
// just for printing effect
for(i = 0; i < depth; i++)
printf(" ");
printf(" v[%c]->v[%c] (backside) \n", flag[vertex], flag[adjVertex]);
}
}
//if(!visited[adjVertex])
else
{
if(vertex == start)
visitFlag = 1;
parent[adjVertex] = vertex;
// just for printing effect
for(i = 0; i < depth; i++)
printf(" ");
printf(" v[%c]->v[%c] (building edge) \n", flag[vertex], flag[adjVertex]);
dfs(adjVertex, depth+1);
}
if(vertex == start && visitFlag) //conducingt dfs for only one adjoining vertex in the given graph
break;
temp = temp->next;
}
}
2.3)printing results(第二张图是对第一张图的补充,我最后添加了 dfsPathSet 方法打印出上述dfs遍历路径所产生的集合):
DFS应用——遍历有向图+判断有向图是否有圈的更多相关文章
- HDU3342:判断有向图中是否存在3元环-Tarjan或拓扑排序
题目大意: 给你一个关系图,判断是否合法.每个人都有师父和徒弟,可以有很多个: 若A是B的师父,B是C的师父,则A也算C的师父. 不合法: 1) . 互为师徒:(有回路) 2) .你的师父是你徒弟 ...
- hdu 1325 判断有向图是否为树
题意:判断有向图是否为树 链接:点我 这题用并查集判断连通,连通后有且仅有1个入度为0,其余入度为1,就是树了 #include<cstdio> #include<iostream& ...
- <数据结构>XDOJ323.判断有向图中是否有环
问题与解答 问题描述 判断有向图中是否有环. 输入格式 输入数据第一行是一个正整数,表示n个有向图,其余数据分成n组,每组第一个为一个整数,表示图中的顶点个数n,顶点数不超过100,之后为有向图的邻接 ...
- C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例
C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例 Unity中循环遍历每个数据,并做出判断 很多时候,游戏在玩家做出判断以后,游戏程序会遍历玩家身上大量的所需数据,然后做出判断,即首先判 ...
- (原创)不过如此的 DFS 深度优先遍历
DFS 深度优先遍历 DFS算法用于遍历图结构,旨在遍历每一个结点,顾名思义,这种方法把遍历的重点放在深度上,什么意思呢?就是在访问过的结点做标记的前提下,一条路走到天黑,我们都知道当每一个结点都有很 ...
- 采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了)
//采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了) #include <iostream> using namespace std; ...
- ZOJ 2475 Benny's Compiler(dfs判断有向图给定点有没有参与构成环)
B - Benny's Compiler Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu ...
- K - Strange Country II 暴力dfs判断有向图是否连通//lxm
You want to visit a strange country. There are n cities in the country. Cities are numbered from 1 t ...
- hdu1269迷宫城堡(判断有向图是否是一个强连通图)
1 /* 题意: 给你一个图,求这个有向图示否是一个强连通图(每两个节点都是可以相互到达的)! 思路1:按正向边dfs一遍,将经过的节点计数,如果记录的节点的个数小于n,那么就说明图按照正向边就不是连 ...
随机推荐
- Java版 数字金额大写转换
需求:读入一个浮点数值,将其转化为中文金额的大写形式.如123.45,转化为:壹佰贰拾叁元肆角伍分. 以下是各种情况要完善: 1. 当金额为整数,只表示整数部分,省略小数部分,并添加“整”字.如123 ...
- 查看IE浏览器安装的插件
请移步至文章:http://blog.sina.com.cn/u/6452627072
- spring spel表达式语言
一.通过bean的id对bean进行引用 1.对其他bean的引用 <property name="dept" value="#{dept}"/> ...
- 位(bit)与字节(byte)
bit就是位,也叫比特位,是计算机表示数据最小的单位. byte就是字节,1byte=8bit,1byte就是1B: 一个字符=2字节: 1KB=1024B 一个英文字母,无论大写和小写都是一个字符: ...
- 利用DM工具Weka进行数据挖掘(分类)的完整过程
利用DM工具Weka进行数据挖掘(分类)的完整过程:
- android的通知栏的实现
package com.example.mynotification; import android.os.Bundle; import android.app.Activity; import an ...
- SeeSharpTools.JXI.DSP.Spectrum 使用
_spectrumTask.Average.Mode = SeeSharpTools.JXI.DSP.Spectrum.SpectrumAverageMode.PeakHold; // NoAvera ...
- canvas 压缩图片的大小
使用 signature_pad canvas 库生成的图片太大.但又没有提供方法来压缩. 当然这是根据你canvas的画布大小决定的,某些原因导致我的画布就得是那么大. 随随便便一个图片转化为bas ...
- IT行业面试指导 计算机行业面试技巧 面试技巧
简历篇 简历是你的的第一张脸,简历写的是否合理,是否吸引人,将决定你能否赢得宝贵的面试机会,迈出第一步! l 姓名,性别,学历,居住地,工作年限,邮箱,手机号 l 填“现居住地”,不要填成“户籍所 ...
- 自己的一个验证电话和ecshop验证电话
//验证电话 function checkPhone($phone) { $preg_mobile = preg_match("/^1\d{10}$/", $phone ); $p ...