• 拓扑排序食用方式


    首先我们要知道什么是拓扑排序,在介绍这一概念之前,我们首先要认识一下什么叫入度和出度。

    入度:是指一个点被多少条边指向。

    出度:是指着一个点出去了多少边。

    通俗点理解拓扑排序就是,只有从前指向后边的点,没有从后边指向前边的边。

    拓扑排序就是要将入度为零的点放入队列,然后删去该点,指向的所有边,入队的顺序就是拓扑排序。

    因此我们可以推断,只要没有自环,一定存在拓扑排序,如果有自环,一定有拓扑排序。

    另外还需要注意,拓扑排序也不是唯一的。

    给定一个 nn 个点 mm 条边的有向图,点的编号是 11 到 nn,图中可能存在重边和自环。

    请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1−1。

    若一个由图中所有点构成的序列 AA 满足:对于图中的每条边 (x,y)(x,y),xx 在 AA 中都出现在 yy 之前,则称 AA 是该图的一个拓扑序列。

    输入格式

    第一行包含两个整数 nn 和 mm。

    接下来 mm 行,每行包含两个整数 xx 和 yy,表示存在一条从点 xx 到点 yy 的有向边 (x,y)(x,y)。

    输出格式

    共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

    否则输出 −1−1。

    数据范围

    1≤n,m≤105   1≤n,m≤105

    输入样例:

    1. 3 3
    2. 1 2
    3. 2 3
    4. 1 3

    输出样例:

    1 2 3

    代码如下:

    1. #include <iostream>
    2. #include <cstring>
    3. #include <queue>
    4. using namespace std;
    5. const int N = 1e05 + 10, M = N * 2;
    6. int read(){
    7. int res = 0 , flag = 1 ;
    8. char c = getchar() ;
    9. while(!isdigit(c)){
    10. if(c == '-') flag = -1 ;
    11. c = getchar() ;
    12. }
    13. while(isdigit(c)){
    14. res = (res << 1) + (res << 3) + (c ^ 48) ;
    15. c = getchar() ;
    16. }
    17. return res * flag ;
    18. }
    19. int n, m;
    20. int h[N], e[N], ne[N], idx;
    21. int d[N];
    22. int q[N];
    23. void add(int a, int b) {
    24. e[idx] = b;
    25. ne[idx] = h[a];
    26. h[a] = idx ++;
    27. }
    28. bool topsort() {
    29. int tt = -1, hh = 0;
    30. for (int i = 1; i < n; i++) {
    31. if(!d[i]) {
    32. q[++tt] = i;
    33. }
    34. }
    35. while (hh <= tt) {
    36. auto u = q[hh++];
    37. for (int i = h[u]; i != -1; i = ne[i]) {
    38. int j = e[i];
    39. if (--d[j] == 0) {
    40. q[++tt] = j;
    41. }
    42. }
    43. }
    44. return tt == n - 1;
    45. }
    46. int main() {
    47. memset(h, -1, sizeof h);
    48. n = read();
    49. m = read();
    50. while (m --) {
    51. int a, b;
    52. a = read();
    53. b = read();
    54. add(a, b);
    55. d[b] ++;
    56. }
    57. if (topsort()) {
    58. for (int i = 0; i < n; i++) {
    59. cout << q[i] << ' ';
    60. }
    61. } else {
    62. puts("-1");
    63. }
    64. return 0;
    65. }

  • 相关阅读:
    48.排列问题求解
    解锁知识管理3.0,生成式人工智能洞察新时代
    聊聊Mybatis的动态Sql之SqlSource
    tqdm高级使用方法(类keras进度条)
    java计算机毕业设计企业客户管理系统源码+mysql数据库+系统+lw文档+部署
    【Kafka】ZooKeeper启动失败报错java.net.BindException: Address already in use: bind
    ESP8266-Arduino编程实例-US-026超声波检测仪驱动
    HTML5中表单提交的4种验证方法
    01| GitOps与DevOps 主流系统
    ubuntu 安装 notepad++
  • 原文地址:https://blog.csdn.net/beloved_yu/article/details/125530493