判断一个图是否有环 无向图 有向图

合集下载

算法之判断一个图是否有环

算法之判断一个图是否有环

算法之判断⼀个图是否有环在⼀些经典算法中,经常需要判断⼀些图是否具有环路,⽐如拓扑排序,需要在最初判断该图是否有环路,如有有环路,则⽆法找到最长的⼀条线,⽐如dijkstra算法,每找到⼀条最短的边,都要判断找到的边和现有的树是否已经构成了环路。

因此,在这篇博客,我们重点来说⼀个判断图是否有环的算法。

⾸先我们介绍⼀个对于⽆向图和有向图通⽤的算法,先讲算法思路: 1.统计各个图中各个点的⼊度数(能够到达这个点的点的数量)。

2.然后找出⼊度数为0的点(⽆向图找⼊度数为1的点)。

3.删除⼊度数为0的点,将其边也删除。

4.重复2,直到所有点⼊度都为0,则为⽆环图,如果找不到⼊度为0的点,则为有环图。

该算法的精髓在于对于⼀个环路(以有向图为例),1->2,2->3,3->1,你会发现找不到⼀个⼊度为0的点,因此这个⽅法是可⾏的。

对于⽆向图和有向图来说,这个算法是通⽤的。

在这我只写了对于有向图的判断的算法,具体的实现代码如下:#include<stdio.h>using namespace std;int graph[100][100];//⽤来存储图的数组bool isVisited[100];//判断这个点是否已经删除int main(){int n,e;while (scanf("%d",&n)!=EOF&&n!=0)//获取点数{for(int i = 0;i<100;i++){isVisited[i] = false;for(int j = 0 ;j<100;j++){graph[i][j] = -1;//初始化数据,所有的边都为-1,代表这两个点之间不能联通}}scanf("%d",&e);//获取边数for(int i = 0 ;i<e;i++)//构建图{int a,b,c;scanf("%d %d %d",&a,&b,&c);graph[a-1][b-1] = c;}int isResult = true;for(int i = 0 ;i<n;i++)//进⾏n次循环,每次循环删除⼀个⼊度为0的点,所以进⾏n次循环{for(int j = 0;j<n;j++)//遍历所有的点,找⼊度为0的点{if(!isVisited[j])//判断该点是否删除{bool isCanVisited = true;//辅助变量,判断这个点是否⼊度为0for(int k = 0;k<n ;k++){if(graph[k][j]!=-1){isCanVisited = false;//如果存在能够访问这个点的边,则该点⼊度不为0}}if(isCanVisited)//如果该点⼊度为0,则下边是删除该点和删除其相邻边{for(int k = 0 ;k<n;k++){graph[j][k] = -1;//删除相邻边,即将值变为-1}isVisited[j] = true;//删除该点}}}isResult = true;for(int j = 0 ;j<n;j++)//进⾏循环判断当前多有点是否已经全部删除,如果全部删除,如果全部删除则跳出,否则继续循环{if(!isVisited[j]){isResult = false;}}if(isResult)break;}isResult = true;for(int i = 0 ;i<n;i++)//在所有点遍历后,则通过这个循环来判断是否所有点都已经删除,如果全部删除,则为⽆环图,否则为有环图{if(!isVisited[i])isResult = false;}if(isResult)printf("⽆环");if(!isResult)printf("有环");}return 0;}实验数据(第⼀⾏输⼊n,e,n代表的是点数,e代表的是边数,接下来e⾏代表具体的边和其权值(权值暂时不⽤理会,是后续拓扑排序所有,因此当前暂时都为1)):5 41 2 11 3 12 3 14 5 15 41 2 12 1 12 3 14 5 1实验结果:。

图习题-数据结构

图习题-数据结构

习题七图一、单项选择题1.设有无向图G=(V,E)和G’=(V’,E’),如G’为G的生成树,则下面不正确的说法是()A.G’为G的子图 B.G’为G的连通分量C.G’为G的极小连通子图且V’=V D.G’是G的无环子图2.任何一个带权的无向连通图的最小生成树()A.只有一棵 B.有一棵或多棵 C.一定有多棵 D.可能不存在3.以下说法正确的是()A.连通分量是无向图中的极小连通子图。

B.强连通分量是有向图中的极大强连通子图。

C.在一个有向图的拓扑序列中,若顶点a在顶点b之前,则图中必有一条弧<a,b>。

D.对有向图G,如果从任意顶点出发进行一次深度优先或广度优先搜索能访问到每个顶点,则该图一定是完全图。

4.图中有关路径的定义是()。

A.由顶点和相邻顶点序偶构成的边所形成的序列 B.由不同顶点所形成的序列C.由不同边所形成的序列 D.上述定义都不是5.设无向图的顶点个数为n,则该图最多有()条边。

A.n-1 B.n(n-1)/2 C. n(n+1)/2 D.0 E.n26.要连通具有n个顶点的有向图,至少需要()条边。

A.n-l B.n C.n+l D.2n7.在一个无向图中,所有顶点的度数之和等于所有边数()倍,在一个有向图中,所有顶点的入度之和等于所有顶点出度之和的()倍。

A.1/2 B.2 C.1 D.48.下列哪一种图的邻接矩阵是对称矩阵?()A.有向图 B.无向图 C.AOV网 D.AOE网9. 下列说法不正确的是()。

A.图的遍历是从给定的源点出发每一个顶点仅被访问一次B.遍历的基本算法有两种:深度遍历和广度遍历C.图的深度遍历不适用于有向图D.图的深度遍历是一个递归过程10.下面哪一方法可以判断出一个有向图是否有环(回路):A.深度优先遍历 B. 拓扑排序 C. 求最短路径 D. 求关键路径11. 在图采用邻接表存储时,求最小生成树的 Prim 算法的时间复杂度为( )。

拓扑排序——判断有向图中是否存在环

拓扑排序——判断有向图中是否存在环

拓扑排序——判断有向图中是否存在环 1// 将先修关系构成⼀张图,由每个数对的第⼆个数字向第⼀个数字连边。

2// ⾸先将所有⼊度为0的点进队,准备拓扑排序。

3// 宽搜过程中,将当前结点所关联的结点的⼊度减1;若发现新的⼊度为0的结点,则将其进队。

4// 最后如果遍历了所有结点,则说明可以满⾜要求;否则,先修关系存在环。

56//查找是否有环7class Solution8 {9public:10bool canFinish(int numCourses, vector<vector<int>>& prerequisites)11 {12 vector<vector<int>> graph(numCourses);13 vector<int> in_degree(numCourses, 0);14for (int i = 0; i < prerequisites.size(); i++)15 {16 in_degree[prerequisites[i][0]]++;17 graph[prerequisites[i][1]].push_back(prerequisites[i][0]);18 }1920 queue<int> q;21 vector<bool> vis(numCourses, false);2223for (int i = 0; i < numCourses; i++)24if (in_degree[i] == 0)25 q.push(i);26while (!q.empty())27 {28int sta = q.front();29 q.pop();30 vis[sta] = true;31//有哪些邻边32for (int i = 0; i < graph[sta].size(); i++)33 {34 in_degree[graph[sta][i]]--;// ⼊度-135if (in_degree[graph[sta][i]] == 0) //⼊度如果为0,加⼊队列36 q.push(graph[sta][i]);37 }38 }3940//0->1->241for (int i = 0; i < numCourses; i++)42if (vis[i] == false)43return false;//有环44return true;//⽆环45 }46 };。

第7章 图-有向无环图

第7章 图-有向无环图

算法的执行步骤: 算法的执行步骤: 1、用一个数组记录每个结点的入度。将入度为零的 、用一个数组记录每个结点的入度。 结点进栈。 结点进栈。 2、将栈中入度为零的结点V输出。 、将栈中入度为零的结点 输出 输出。 3、根据邻接表找到结点 的所有的邻接结点, 并将 、根据邻接表找到结点V的所有的邻接结点 的所有的邻接结点, 这些邻接结点的入度减一。 这些邻接结点的入度减一 。 如果某一结点的入度变 为零,则进栈。 为零,则进栈。
3
2
3、找到全为零的第 k 列,输出 k 、 4、将第 k 行的全部元素置为零 、 行的全部元素置为零
…………………
7
53、4;直至所有元素输出完毕。 、 ;直至所有元素输出完毕。
1 2 3 4 5 6 7
0 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0
template<class T> int BinaryTree <T>:: NumOfOne ( node <T> *t )
{ int k=0; if (t==NULL ) //空二叉树 //空二叉树 return 0; if (t所指结点 的度为 k=1 所指结点 的度为1) k=1; d1= NumOfOne ( t->lchild); //递归求左子树叶结点数 //递归求左子树叶结点数 d2= NumOfOne ( t->rchild); } //递归求右子树叶结点数 //递归求右子树叶结点数 return (d1+d2+k);
A B
AOE网络:结点为事件,有向边指向表示事件的执行次序。 网络:结点为事件,有向边指向表示事件的执行次序。 网络 有向边定义为活动,边的权值为活动进行所需要的时间。 有向边定义为活动,边的权值为活动进行所需要的时间。

图论及其应用习题答案

图论及其应用习题答案

图论及其应用习题答案图论及其应用习题答案图论是数学的一个分支,研究的是图的性质和图之间的关系。

图是由节点和边组成的,节点表示对象,边表示对象之间的关系。

图论在计算机科学、电子工程、物理学等领域有着广泛的应用。

下面是一些图论习题的解答,希望对读者有所帮助。

1. 问题:给定一个无向图G,求图中的最大连通子图的节点数。

解答:最大连通子图的节点数等于图中的连通分量个数。

连通分量是指在图中,任意两个节点之间存在路径相连。

我们可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来遍历图,统计连通分量的个数。

2. 问题:给定一个有向图G,判断是否存在从节点A到节点B的路径。

解答:我们可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来遍历图,查找从节点A到节点B的路径。

如果能够找到一条路径,则存在从节点A到节点B的路径;否则,不存在。

3. 问题:给定一个有向图G,判断是否存在环。

解答:我们可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来遍历图,同时记录遍历过程中的访问状态。

如果在搜索过程中遇到已经访问过的节点,则存在环;否则,不存在。

4. 问题:给定一个加权无向图G,求图中的最小生成树。

解答:最小生成树是指在无向图中,选择一部分边,使得这些边连接了图中的所有节点,并且总权重最小。

我们可以使用Prim算法或Kruskal算法来求解最小生成树。

5. 问题:给定一个有向图G,求图中的拓扑排序。

解答:拓扑排序是指将有向图中的节点线性排序,使得对于任意一条有向边(u, v),节点u在排序中出现在节点v之前。

我们可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来遍历图,同时记录节点的访问顺序,得到拓扑排序。

6. 问题:给定一个加权有向图G和两个节点A、B,求从节点A到节点B的最短路径。

解答:我们可以使用Dijkstra算法或Bellman-Ford算法来求解从节点A到节点B的最短路径。

这些算法会根据边的权重来计算最短路径。

图论选择题解析docx

图论选择题解析docx

数据结构——图选择题整理1.设完全图Kn,有n个结点(n≥2),m条边,当()时,K,中存在欧拉回路。

A.m为奇数B.n为偶数C.n为奇数D.m为偶数解析:答案C完全图是一个简单的无向图,其中每对不同的顶点之间都恰连有一条边相连。

n 个端点的完全图有n个端点以及n(n-1)/2条边,因此完全图Kn的每个结点的度都为n-1,所以若存在欧拉回路则n-1必为偶数。

n必为奇数。

选C。

2、若从无向图的任意顶点出发进行一次深度优先搜索即可访问所有顶点,则该图一定是()A、强连通图B、连通图C、有回路D、一棵树解析:选B对于A,强连通图的概念是在有向图中的。

对于B,连通图证明任意两个顶点之间一定能够相连,因此一定可以到达。

对于C,有环图不一定是连通图不一定任意两个顶点均能到达。

对于D,树是可以,但是不是树也可以,题目中说的太肯定了,不能选,比如下图就不是树,但可以完成题目中要求的功能。

2、对于一个有n个顶点的图:若是连通无向图,其边的个数至少为();若是强连通有向图,其边的个数至少为()A、n-1,nB、n-1,n(n-1)C、n,nD、n,n(n-1)解析:选A对于连通无向图,至少需要n-1条边。

对于强连通有向图,只要能形成一个大环就可以从任意一点到另一点。

3、设有无向图G=(V,E)和G'=(V',E'),若G’是G的生成树,则下列不正确的是()a.G'为G的连通分量b.G'为G的无环子图c.G'为G的极小连通子图且V'=VA、a和bB、只有cC、b和cD、只有a解析:选D极大连通子图简称连通分量,生成树是极小连通子图。

故a不对,c对。

生成树无环,故b对4.带权有向图G用邻接矩阵存储,则vi的入度等于邻接矩阵中()A、第i行非∞的元素个数B、第i列非∞的元素个数C、第i行非∞且非0的元素个数D、第i列非∞且非0的元素个数解析:选D带权有向图的邻接矩阵中,非0和∞的数字表示两点间边的权值。

有向图与无向图的性质与算法

有向图与无向图的性质与算法

有向图与无向图的性质与算法1. 引言在图论中,有向图和无向图是两种最基本的图模型。

它们在表达和解决各类实际问题时具有重要的应用价值。

本文将介绍有向图和无向图的性质以及相关算法,以便读者对其有更深入的理解。

2. 有向图的性质有向图是由一系列顶点和有方向的边组成的图模型。

以下是有向图的几个重要性质:2.1 有向边的方向性与无向图不同,有向图中的边是有方向的,它们从一个顶点指向另一个顶点。

这种方向性在描述一些实际问题时非常有用,比如描述物流运输的路径。

2.2 顶点的入度和出度有向图中的每个顶点都有一个入度和一个出度。

顶点的入度是指指向该顶点的边的数量,而出度是指从该顶点出发的边的数量。

通过计算入度和出度,我们可以了解顶点在图中的连接情况。

2.3 有向环和拓扑排序有向图中存在一个重要的概念,即有向环。

有向环是指从一个顶点出发,经过若干个有向边后又回到该顶点的路径。

有向环在一些问题的分析和解决中具有特殊意义。

而拓扑排序是一种常用的对有向无环图进行排序的方法,它可以按照顶点之间的依赖关系进行排序。

3. 无向图的性质无向图是由一系列顶点和无方向的边组成的图模型。

以下是无向图的几个重要性质:3.1 无向边的无方向性与有向图不同,无向图中的边是无方向的,它们连接着两个顶点,代表了两个顶点之间的关系。

无向图可以用来表示一些没有方向性的问题,比如社交网络中的好友关系。

3.2 顶点的度数无向图中的顶点的度数是指与该顶点相连的边的数量。

顶点的度数越高,说明该顶点在图中的重要性越高,具有更多的连接关系。

3.3 联通性和连通分量无向图中有一个关键性质,即联通性。

若两个顶点之间存在一条连接它们的路径,则称这两个顶点是连通的。

连通分量则是将图中所有连通的顶点分为若干个集合,每个集合内的顶点都是连通的。

4. 算法与应用4.1 有向图的最短路径算法有向图中的最短路径算法是指寻找从一个顶点到另一个顶点的最短路径的方法。

其中,Dijkstra算法和Bellman-Ford算法是常用的有向图最短路径算法。

数据结构考前复习3

数据结构考前复习3

第四章串一、选择题1.下面关于串的的叙述中,哪一个是不正确的?( B )A.串是字符的有限序列 B.空串是由空格构成的串C.模式匹配是串的一种重要运算 D.串既可以采用顺序存储,也可以采用链式存储3.设有两个串p和q,其中q是p的子串,求q在p中首次出现的位置的算法称为( C )A.求子串 B.联接 C.匹配 D.求串长10.串的长度是指( B )A.串中所含不同字母的个数 B.串中所含字符的个数C.串中所含不同字符的个数 D.串中所含非空格字符的个数二、填空题1.空格串是指由空格字符(ASCII值32)所组成的字符串,其长度等于空格个数__。

2.组成串的数据元素只能是__字符______。

3.一个字符串中任意个连续的字符组成的子序列称为该串的子串。

四、应用题1.名词解释:串串是零个至多个字符组成的有限序列。

从数据结构角度讲,串属于线性结构。

与线性表的特殊性在于串的元素是字符。

2.描述以下概念的区别:空格串与空串。

空格是一个字符,其ASCII码值是32。

空格串是由空格组成的串,其长度等于空格的个数。

空串是不含任何字符的串,即空串的长度是零。

第六章树和二叉树一、选择题1.已知一算术表达式的中缀形式为 A+B*C-D/E,后缀形式为ABC*+DE/-,其前缀形式为( D )A.-A+B*C/DE B. -A+B*CD/E C.-+*ABC/DE D. -+A*BC/DE 4. 设树T的度为4,其中度为1,2,3和4的结点个数分别为4,2,1,1 则T中的叶子数为( D )A.5 B.6 C.7 D.85. 在下述结论中,正确的是( D )①只有一个结点的二叉树的度为0; ②二叉树的度为2;③二叉树的左右子树可任意交换;④深度为K的完全二叉树的结点个数小于或等于深度相同的满二叉树。

A.①②③ B.②③④ C.②④ D.①④结点的度:一个结点的子数个数称为此结点的度数的度;树中所有结点的读的最大值6. 设森林F对应的二叉树为B,它有m个结点,B的根为p,p的右子树结点个数为n,森林F中第一棵树的结点个数是( A )A.m-n B.m-n-1 C.n+1 D.条件不足,无法确定8.若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是( B )A.9 B.11 C.15 D.不确定10.设森林F中有三棵树,第一,第二,第三棵树的结点个数分别为M1,M2和M3。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、无向图:方法1:∙如果存在回路,则必存在一个子图,是一个环路。

环路中所有顶点的度>=2。

∙ n算法:第一步:删除所有度<=1的顶点及相关的边,并将另外与这些边相关的其它顶点的度减一。

第二步:将度数变为1的顶点排入队列,并从该队列中取出一个顶点重复步骤一。

如果最后还有未删除顶点,则存在环,否则没有环。

∙ n算法分析:由于有m条边,n个顶点。

i)如果m>=n,则根据图论知识可直接判断存在环路。

(证明:如果没有环路,则该图必然是k棵树k>=1。

根据树的性质,边的数目m = n-k。

k>=1,所以:m<n)ii)如果m<n 则按照上面的算法每删除一个度为0的顶点操作一次(最多n次),或每删除一个度为1的顶点(同时删一条边)操作一次(最多m次)。

这两种操作的总数不会超过m+n。

由于m<n,所以算法复杂度为O(n)。

∙注:该方法,算法复杂度不止O(V),首先初始时刻统计所有顶点的度的时候,复杂度为(V + E),即使在后来的循环中E>=V,这样算法的复杂度也只能为O(V + E)。

其次,在每次循环时,删除度为1的顶点,那么就必须将与这个顶点相连的点的度减一,并且执行delete node from list[list[node]],这里查找的复杂度为list[list[node]]的长度,只有这样才能保证当degree[i]=1时,list[i]里面只有一个点。

这样最差的复杂度就为O(EV)了。

方法2:DFS搜索图,图中的边只可能是树边或反向边,一旦发现反向边,则表明存在环。

该算法的复杂度为O(V)。

方法3:摘自:/lzrzhao/archive/2008/03/13/2175787.aspx PS:此方法于2011-6-12补充假定:图顶点个数为M,边条数为E遍历一遍,判断图分为几部分(假定为P部分,即图有P 个连通分量)对于每一个连通分量,如果无环则只能是树,即:边数=结点数-1只要有一个满足边数> 结点数-1原图就有环将P个连通分量的不等式相加,就得到:P1:E1=M1-1P2:E2=M2-1...PN:EN>MN-1所有边数(E) > 所有结点数(M) - 连通分量个数(P)即: E + P > M 所以只要判断结果 E + P > M 就表示原图有环,否则无环.实例代码如下:1.#include<iostream>2.#include<malloc.h>ing namespace std;4.#define maxNum 100 //定义邻接举证的最大定点数5.int visited[maxNum];//通过visited数组来标记这个顶点是否被访问过,0表示未被访问,1表示被访问6.int DFS_Count;//连通部件个数,用于测试无向图是否连通,DFS_Count=1表示只有一个连通部件,所以整个无向图是连通的7.int pre[maxNum];8.int post[maxNum];9.int point;//pre和post的值10.11.//图的邻接矩阵表示结构12.typedef struct13.{14.char v[maxNum];//图的顶点信息15.int e[maxNum][maxNum];//图的顶点信息16.int vNum;//顶点个数17.int eNum;//边的个数18.}graph;19.void createGraph(graph *g);//创建图g20.void DFS(graph *g);//深度优先遍历图g21.void dfs(graph *g,int i);//从顶点i开始深度优先遍历与其相邻的点22.void dfs(graph *g,int i)23.{24.//cout<<"顶点"<<g->v[i]<<"已经被访问"<<endl;25. cout<<"顶点"<<i<<"已经被访问"<<endl;26. visited[i]=1;//标记顶点i被访问27. pre[i]=++point;28.for(int j=1;j<=g->vNum;j++)29. {30.if(g->e[i][j]!=0&&visited[j]==0)31. dfs(g,j);32. }33. post[i]=++point;34.}35.36.void DFS(graph *g)37.{38.int i;39.//初始化visited数组,表示一开始所有顶点都未被访问过40.for(i=1;i<=g->vNum;i++)41. {42. visited[i]=0;43. pre[i]=0;44. post[i]=0;45. }46.//初始化pre和post47. point=0;48.//初始化连通部件数为049. DFS_Count=0;50.//深度优先搜索51.for(i=1;i<=g->vNum;i++)52. {53.if(visited[i]==0)//如果这个顶点为被访问过,则从i顶点出发进行深度优先遍历54. {55. DFS_Count++;//统计调用void dfs(graph *g,int i);的次数56. dfs(g,i);57. }58. }59.}60.void createGraph(graph *g)//创建图g61.{62. cout<<"正在创建无向图..."<<endl;63. cout<<"请输入顶点个数vNum:";64. cin>>g->vNum;65. cout<<"请输入边的个数eNum:";66. cin>>g->eNum;67.int i,j;68.//输入顶点信息69.//cout<<"请输入顶点信息:"<<endl;70.//for(i=0;i<g->vNum;i++)71.// cin>>g->v[i];72.//初始画图g73.for(i=1;i<=g->vNum;i++)74.for(j=1;j<=g->vNum;j++)75. g->e[i][j]=0;76.//输入边的情况77. cout<<"请输入边的头和尾"<<endl;78.for(int k=0;k<g->eNum;k++)79. {80. cin>>i>>j;81. g->e[i][j]=1;82. g->e[j][i]=1;//无向图对称83. }84.}85.int main()86.{87. graph *g;88. g=(graph*)malloc(sizeof(graph));89. createGraph(g);//创建图g90. DFS(g);//深度优先遍历91.//连通部件数,用于判断是否连通图92. cout<<"连通部件数量:";93. cout<<DFS_Count<<endl;94.if(DFS_Count==1)95. cout<<"图g是连通图"<<endl;96.else if(DFS_Count>1)97. cout<<"图g不是连通图"<<endl;98.//各顶点的pre和post值99.for(int i=1;i<=g->vNum;i++)100. cout<<"顶点"<<i<<"的pre和post分别为:"<<pre[i]<<" "<<post[i]<<endl;101.//cout<<endl;102.//判断无向图中是否有环103.if(g->eNum+DFS_Count>g->vNum)104. cout<<"图g中存在环"<<endl;105.else106. cout<<"图g中不存在环"<<endl;107.int k;108. cin>>k;109.return 0;110.}111./*112.输入:113.正在创建无向图...114.请输入顶点个数vNum:10115.请输入边的个数eNum:9116.请输入边的头和尾117.1 2118.1 4119.2 5120.2 6121.4 7122.5 9123.6 3124.7 8125.9 10126.*/注意:有向图不能使用此方法。

比如1->2,1-3,2->3,4->5,如果使用上述方法会判定为含有还,但并非如此。

二、有向图:主要有深度优先和拓扑排序2中方法1、拓扑排序,如果能够用拓扑排序完成对图中所有节点的排序的话,就说明这个图中没有环,而如果不能完成,则说明有环。

2、可以用Strongly Connected Components来做,我们可以回忆一下强连通子图的概念,就是说对于一个图的某个子图,该子图中的任意u->v,必有v->u,则这是一个强连通子图。

这个限定正好是环的概念。

所以我想,通过寻找图的强连通子图的方法应该可以找出一个图中到底有没有环、有几个环。

3、就是用一个改进的DFS刚看到这个问题的时候,我想单纯用DFS就可以解决问题了。

但细想一下,是不能够的。

如果题目给出的是一个无向图,那么OK,DFS是可以解决的。

但无向图得不出正确结果的。

比如:A->B,A->C->B,我们用DFS来处理这个图,我们会得出它有环,但其实没有。

我们可以对DFS稍加变化,来解决这个问题。

解决的方法如下:图中的一个节点,根据其C[N]的值,有三种状态:0,此节点没有被访问过-1,被访问过至少1次,其后代节点正在被访问中1,其后代节点都被访问过。

相关文档
最新文档