• 拓扑排序:acwing 848. 有向图的拓扑序列


    1. #include
    2. using namespace std;
    3. const int N=1e5+10;
    4. int n,m;
    5. int h[N],e[N],ne[N],idx;
    6. int q[N],d[N];
    7. void add(int a,int b)
    8. {
    9. e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    10. }
    11. bool topsort()
    12. {
    13. int hh=0,tt=-1;
    14. for(int i=1;i<=n;i++)
    15. {
    16. if(!d[i]) q[++tt]=i;
    17. }
    18. while(hh<=tt)
    19. {
    20. int t=q[hh++];
    21. for(int i=h[t];i!=-1;i=ne[i])
    22. {
    23. int j=e[i];
    24. if(--d[j]==0) q[++tt]=j;
    25. }
    26. }
    27. return tt==n-1;
    28. }
    29. int main()
    30. {
    31. memset(h,-1,sizeof h);
    32. scanf("%d%d",&n,&m);
    33. for(int i=0;i
    34. {
    35. int a,b;
    36. scanf("%d%d",&a,&b);
    37. add(a,b);
    38. d[b]++;
    39. }
    40. if(!topsort()) printf("-1\n");
    41. else
    42. {
    43. for(int i=0;iprintf("%d ",q[i]);
    44. printf("\n");
    45. }
    46. return 0;
    47. }

      拓扑排序,可以理解为前置知识,比如说学习高中数学,我们需要初中数学的前置知识,学习初中数学我们需要小学数学的前置知识。

      或者我们进行某种通关游戏,只有通过前面的关卡,我们才可以解锁后面的关卡。

      拓扑排序体现在图里面就是,一个点的入度为0的话,我们就把这个点删除,连同这个点指出的边,一直重复上述操作,如果可以把所有的点都删除,我们称这个图可以进行拓扑排序。

      实现拓扑排序,我们可以使用数组模拟队列来实现(因为我们最后还需要输出所有的点,直接使用stl里的队列的话,因为点被pop出队了,不方便保存数据)

      建立邻接表代码模板

    1. void add(int a,int b)
    2. {
    3. e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    4. }

      d[ ] 数组存储的是每一个节点的入度,首先把所有入度为0的点存在队列里面,然后,遍历邻接表,删除入度为0的点和从该点出发的边(其实就是让该点指向的下一个点的入度减小1),如果出现入度为0的点,就把这个点存进队列里面,最后判断是不是所有的点都在队列里面,如果所有点都在队列里面,说明该图可以进行拓扑排序,输出队列里面所有点即可。

      使用邻接表建立有向图的时候,顺便使用d[ ]数组保存每一个节点的入度,也就是使用这一行代码

            d[b]++;

     

  • 相关阅读:
    U盘显示无媒体怎么办?方法很简单
    SQL必备基础知识
    BL808:【M1s DOCK开发板】与LVGL 使用体验
    Git使用
    【Java】传输层协议TCP
    paddleocr识别模型训练记录
    例39:使用List控件
    png图片打包plist工具,手把手教你使用pngPackerGUI_V2.0
    Android 明年将不再支持 32 位应用
    基于BP神经网络的电力负荷预测附Matlab代码
  • 原文地址:https://blog.csdn.net/L3102250566/article/details/133941741