拓扑排序,判断有向图中是否有环

【原创】

今天我们来聊聊有向图中环的判断,在数据结构中我们知道,通过拓扑排序可以判断有向图中是否存在环,对于有向图的存储我们采用邻接表的形势,这里为了简化链表的操作,我们省略了链表,避免了指针的麻烦,直接采用了c++中的vector来模拟链表,操作更加的方便;具体详细的使用,建议百度一下,这里不多说,至于拓扑排序的具体思想,相信大家应该都了解,那么直接上代码,如果有不理解的,建议查阅数据结构书籍,搞懂思想,结合这份代码,很好理解

 1 #include <stdio.h>
 2 #include <queue>
 3 #include<vector>
 4 #include<stdlib.h>
 5 using namespace std;
 6 //拓扑排序中使用的对列和模拟链表的向量
 7 vector<int> edge[501];//邻接链表
 8 queue<int> Q;//保存入股为0的节点
 9 int main(){
10  //拓扑排序,判断一个有向图中是否存在环
11     int inDegree[501];//统计每一个节点的入度;
12     int n,m;
13     while (scanf("%d%d",&n,&m)!=EOF) {//多组数据的测试
14         if (m==0&&n==0) break;
15         for (int i = 0; i<n; i++) {
16             inDegree[i] = 0;//刚开始的节点入度均为0
17             edge[i].clear();//清除前一组数据的残留
18         }
19         while(m--!=0){
20             int a,b;//输入m组节点关系
21             scanf("%d%d",&a,&b);
22             inDegree[b]++;//出现了一条边指向b,所以入度增加1
23             edge[a].push_back(b);//
24         }
25         while (Q.empty()==false) {
26             Q.pop();//清除之前的数据
27         }
28         for(int i = 0;i<n;i++){
29             if (inDegree[i]==0) {
30                 Q.push(i);
31             }
32         }
33             int cnt = 0;
34             while (Q.empty()==false) {//当队列中还有入度为0的点
35                 int newP = Q.front();
36                 Q.pop();//这里不需要保留拓扑排序的路径,因而不需要保存弹出来的值
37                 cnt++;
38                 for (int i = 0; i<edge[newP].size(); i++) {
39                     inDegree[edge[newP][i]]--;//去除一条边后,将所指向的后继节点的如度减1
40                     if (inDegree[edge[newP][i]]==0) {
41                         Q.push(edge[newP][i]);
42                     }
43                 }
44             }
45         if (cnt==n) {
46             puts("YES");
47         }else{
48             puts("NO");
49         }
50     }
51 return 0;
52 }
53 /**************************************************************
54     Problem: 1448
55     User: Numen_fan
56     Language: C++
57     Result: Accepted
58     Time:10 ms
59     Memory:1064 kb
60 ****************************************************************/

注意:这份代码,输入两个数字n、m,n表示有n个节点,m表示有m对关系,即接下来有m行,每一行两个数字a、b,表示a到b有边,;同时这里可以测试多组数据,这种编程思想是很好的,不用测试一组数据酒run一次,麻烦,同时,看到代码35-37行中,这里只计算cnt总数,并没有保存拓扑排序的序列,如果需要求出序列,也很容易吧,将newP节点保存即可,本例子中采用queue队列来保存入度为0 的节点,那么其实也可以用stack来保存,原因很简单,因为拓扑排序不唯一;

时间: 2024-08-24 17:51:38

拓扑排序,判断有向图中是否有环的相关文章

LeetCode 210. Course Schedule II(拓扑排序-求有向图中是否存在环)

和LeetCode 207. Course Schedule(拓扑排序-求有向图中是否存在环)类似. 注意到,在for (auto p: prerequistites)中特判了输入中可能出现的平行边或自环. 代码: class Solution { public: vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) { // [0, {1, 2, 3}], me

LeetCode 207. Course Schedule(拓扑排序-求有向图中是否存在环)

求有向图中是否有环. 法一:拓扑排序 用一个队列维护所有入度为0的节点,每次弹出一个节点v,查看从v可达的所有节点u; 将u的入读减一,若u的入度此时为0, 则将u加入队列. 在队列为空时,检查所有节点的入度,若所有节点入度都为0, 则存在这样的一个拓扑排序 -- 有向图中不存在环. 代码: class Solution { public: bool canFinish(int numCourses, vector<pair<int, int>>& prerequisite

拓扑排序判断有向图是否有回路

1 #include <iostream> 2 #include <queue> 3 #include <string> 4 using namespace std; 5 6 //表结点 7 typedef struct ArcNode{ 8 int adjvex;//该弧所指向的顶点的位置 9 ArcNode *nextarc; 10 }ArcNode; 11 12 //头结点 13 typedef struct VNode{ 14 string data;//顶点信

判断有向图中是否存在环

1 // 将先修关系构成一张图,由每个数对的第二个数字向第一个数字连边. 2 // 首先将所有入度为0的点进队,准备拓扑排序. 3 // 宽搜过程中,将当前结点所关联的结点的入度减1:若发现新的入度为0的结点,则将其进队. 4 // 最后如果遍历了所有结点,则说明可以满足要求:否则,先修关系存在环. 5 6 //查找是否有环 7 class Solution 8 { 9 public: 10 bool canFinish(int numCourses, vector<vector<int>

判断有向图中是否有环

1 #include<iostream> 2 #include<malloc.h> 3 using namespace std; 4 #define maxNum 110 ///定义邻接举证的最大定点数 5 int pre[maxNum]; 6 int post[maxNum]; 7 int point=0;///pre和post的值 8 bool is_DAG=true;///标识位,表示有向无环图 9 /* 10 顶点颜色表 vis[u] 11 0 白色,未被访问过的节点标白色

判断无向图/有向图中是否存在环

本文主要针对如何判断有向图/无向图中是否存在环的问题进行简单的论述. 一 无向图 1.利用DFS进行判断 利用DFS判断有向图是否存在环,是最为常用的一种方法,虽然这种方法很常用,但可参考的代码的实现比较少,下面对这种方法及其实现进行详细的阐述. 首先,利用DFS判断无向图中是否换的原理是:若在深度优先搜索的过程中遇到回边(即指向已经访问过的顶点的边),则必定存在环. 所以说,是否存在环的关键在于是否存在满足条件的"回边",那么如何判断回边呢? (1)首先,对图中的所有顶点定义三种状态

UVA-1572 Self-Assembly(拓扑排序判断有向环)

题目: 给出几种正方形,每种正方形有无穷多个.在连接的时候正方形可以旋转.翻转. 正方形的每条边上都有一个大写英文字母加'+'或'-'.00,当字母相同符号不同时,这两条边可以相连接,00不能和任何边相连. 判断给出的正方形如果能无限连接下去就输出unbounded.不能就输出bounded. 思路: 这个题读完之后,一点思路都没有,看完紫书上的分析知道是用拓扑排序来判断有向环,但具体的构造还是不会-- 1.将每个正方形看作一条边,在正方形每两条边上的字母(不包括00)之间连一条有向边构成一个有

hdoj 4324 Triangle LOVE【拓扑排序判断是否存在环】

Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3566    Accepted Submission(s): 1395 Problem Description Recently, scientists find that there is love between any of two people. For

判断图中是否有环的方法

一.无向图 方法一:n算法: 原理是: 如果存在回路,则必存在一个子图,是一个环路.环路中所有顶点的度>=2. 第一步:删除所有度<=1的顶点及相关的边,并将另外与这些边相关的其它顶点的度减一. 第二步:将度数变为1的顶点排入队列,并从该队列中取出一个顶点重复步骤一. 如果最后还有未删除顶点,则存在环,否则没有环. 方法2: DFS搜索图,图中的边只可能是树边或反向边,一旦发现反向边,则表明存在环.该算法的复杂度为O(V). 二.有向图 主要有深度优先和拓扑排序两种方法 判断图中是否有环的方法