拓扑排序

目录

拓扑排序

有向图的拓扑排序


拓扑排序

  • 一个有向图,如果图中有入度为 0 的点,就把这个点删掉,同时也删掉这个点所连的边。

  • 一直进行上面出处理,如果所有点都能被删掉,则这个图可以进行拓扑排序。

举例子:

开始时,图是这样的状态,发现A的入度为 0,所以删除A和A上所连的边,结果如下图:

这时发现B的入度为 0,C的入度为 0,所以删除B和B上所连的边、C和C上所连的边,结果如下图:

这时发现发现D的入度为 0,所以删除D和D上所连的边(如果有就删)。

  • 所有的边都是从前指向后的

  • 有向图才有拓扑排序

  • 图中有环,一定没有拓扑排序

  • 一个有向无环图一定是由一个拓扑排序的

  • 一个有向无环图,一定存在一个入度为0的点

有向图的拓扑排序

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int e[N], ne[N], idx;//邻接表存储图
int h[N];
int q[N], hh = 0, tt = -1;//队列保存入度为0的点,也就是能够输出的点,
int n, m;//保存图的点数和边数
int d[N];保存各个点的入度

//链表存储有向图 
void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void topsort(){
	//把所有的入度为0的点放入队列 
    for(int i = 1; i <= n; i++){//遍历一遍顶点的入度。
        if(d[i] == 0)//如果入度为 0, 则可以入队列
            q[++tt] = i;
    }
    
    //整个拓扑排序思路是采用每次遍历一个点,就删除一条边,等于入度减1。
	//如果这个图是拓扑图,最终结果就是所有点都在队列中
	//如果不是拓扑图就会还有一些点还有边。 
    while(tt >= hh){//循环处理队列中点的
        int a = q[hh++];
        
        for(int i = h[a]; i != -1; i = ne[i]){//循环删除 a 发出的边
            int b = e[i];//a 有一条边指向b
            d[b]--;//删除边后,b的入度减1
            if(d[b] == 0)//如果b的入度减为 0,则 b 可以输出,入队列
                q[++tt] = b;
        }
        
    }
    
    if(tt == n - 1){//如果队列中的点的个数与图中点的个数相同,则可以进行拓扑排序
        for(int i = 0; i < n; i++){//队列中保存了所有入度为0的点,依次输出
            cout << q[i] << " ";
        }
    }
    else//如果队列中的点的个数与图中点的个数不相同,则可以进行拓扑排序
        cout << -1;//输出-1,代表错误
}


int main(){
    cin >> n >> m;//保存点的个数和边的个数
    memset(h, -1, sizeof h);//初始化邻接矩阵
    while (m -- ){//依次读入边
        int a, b;
        cin >> a >> b;
        d[b]++;//顶点b的入度+1
        add(a, b);//添加到邻接矩阵
    }
    topsort();//进行拓扑排序
    return 0;
}

板子

bool topsort()
{
    int hh = 0, tt = -1;

    // d[i] 存储点i的入度
    for (int i = 1; i <= n; i ++ )
        if (!d[i])
            q[ ++ tt] = i;

    while (hh <= tt)
    {
        int t = q[hh ++ ];

        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (-- d[j] == 0)
                q[ ++ tt] = j;
        }
    }

    // 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
    return tt == n - 1;
}

相关推荐

  1. 【模板】拓扑排序

    2024-01-01 04:36:02       36 阅读
  2. 【算法】拓扑排序

    2024-01-01 04:36:02       18 阅读
  3. 复习拓扑排序

    2024-01-01 04:36:02       19 阅读
  4. 拓扑排序板子

    2024-01-01 04:36:02       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-01 04:36:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-01 04:36:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-01 04:36:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-01 04:36:02       18 阅读

热门阅读

  1. 预训练模型下载和使用

    2024-01-01 04:36:02       40 阅读
  2. 若依报500异常,只有前端没有后端

    2024-01-01 04:36:02       35 阅读
  3. Object-c初步学习 三

    2024-01-01 04:36:02       33 阅读
  4. Prometheus监控Linux

    2024-01-01 04:36:02       39 阅读
  5. vue3 key Attribute 的变化

    2024-01-01 04:36:02       40 阅读
  6. C++导论

    2024-01-01 04:36:02       31 阅读
  7. Django REST framework -10-自定义认证类

    2024-01-01 04:36:02       34 阅读
  8. 【WPF.NET开发】将路由事件标记为已处理和类处理

    2024-01-01 04:36:02       33 阅读
  9. 9、python-闭包

    2024-01-01 04:36:02       42 阅读
  10. 【PostgreSQL如何查看page、index的详细信息】

    2024-01-01 04:36:02       41 阅读
  11. 深入理解SqlSugar ORM框架的使用与实战

    2024-01-01 04:36:02       30 阅读
  12. 【Delphi 基础知识 8】常用的运算符

    2024-01-01 04:36:02       39 阅读
  13. 长度最小的子数组

    2024-01-01 04:36:02       37 阅读
  14. 数据库查询优化

    2024-01-01 04:36:02       39 阅读
  15. PostgreSQL | 概念 | 什么是OLTP&OLAP?

    2024-01-01 04:36:02       39 阅读
  16. 组合设计模式

    2024-01-01 04:36:02       33 阅读
  17. Ant Design Vue表单组件a-form-item-rest使用

    2024-01-01 04:36:02       39 阅读
  18. 如何将Git的语言设置为中文

    2024-01-01 04:36:02       40 阅读
  19. 腾讯云轻量应用服务器测评,2核4G5M配置3年756元

    2024-01-01 04:36:02       37 阅读