zoukankan      html  css  js  c++  java
  • 拓扑排序,判断有向图中是否有环

    【原创】

    今天我们来聊聊有向图中环的判断,在数据结构中我们知道,通过拓扑排序可以判断有向图中是否存在环,对于有向图的存储我们采用邻接表的形势,这里为了简化链表的操作,我们省略了链表,避免了指针的麻烦,直接采用了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来保存,原因很简单,因为拓扑排序不唯一;

  • 相关阅读:
    链表操作
    51nod1085-----01背包
    51nod1046快速幂取余
    51nod贪心算法入门-----任务分配问题
    51nod动态规划-----矩阵取数
    51nod贪心算法入门-----独木舟问题
    POJ2255二叉树
    POJ1182并查集
    POJ1384完全背包问题
    20162313_苑洪铭_ 第7周学习总结
  • 原文地址:https://www.cnblogs.com/numen-fan/p/6509051.html
Copyright © 2011-2022 走看看