拓扑排序

淩亂°似流年 2021-12-23 02:43 459阅读 0赞

拓扑排序:

拓扑排序是根据离散数学中有关偏序与全序定义的。

0_1314168765l7fq.gif

若一个集合 X 上的关系 R 是自反的 反对称的和传递的,就称为 R 是集合 X 上的 偏序关系

设 R 是集合 X 上的偏序,若对每个 x ,y 属于 x ,必有 xRy 或 yRx,则称 R 是集合 X 上的全序关系。

直观的讲,偏序就是一个点的集合中只有部分顶点可以确立优先关系。而全序就是点的集合中任意两个顶点都可以确立优先关系,而由某个集合上的一个偏序得到该集合的一个全序的操作就是拓扑排序。

由上图可以看出,能够满足拓扑排序,首先这个图是一个有向无环图,即每一个路径都是有向的,而且其中不行成环,如果形成环就不能进行拓扑排序。

例入上图南阳理工学院课表安排:

课程代号 课程名称 先行课

C1 C2 计算机应用基础,c语言 无

C3 网页制作 C1

C4 C++语言程序设计 C1,C2

C5 数据库技术 C3,C4

C6 汇编语言 C2,C4

C7 嵌入式开发 C4,C5,C6

这就是一个类似课程先后关系的有向图,要我们根据前面的关系把这些科安排在不同的学期(即学习的先后关系)。这就要求我们对他进行一个拓扑排序。

可以看出这个排序的结果是C1,C2,C3,C4,C5,C6,C7 或者是 C2,C1,C4,C6,C3,C7。即排序后的结果不是唯一的。

那么我们怎样实现对这样一个图的拓扑排序呢,我们直到图的常用存法有两种,即临接矩阵和临接表。临接矩阵存稠密图,临接表存稀疏图,先介绍一种通过临接表存储通过DFs思想实现的算法。

从一个没有入度的节点出发,深搜回溯的时候保存最深处的点加到拓扑排序的首部。代码:

  1. int map[Max][Max];
  2. int vis[Max],topo[Max];
  3. int m,n;
  4. bool Dfs(int u)
  5. {
  6. vis[u]=-1;
  7. for(int v=1;v<=n;v++)
  8. {
  9. if(map[u][v])
  10. {
  11. if(vis[v]<0) {return false;}
  12. else if(!vis[v]&&!Dfs(v)) return false;
  13. }
  14. }
  15. vis[u] = 1;topo[--t]=u;
  16. return true;
  17. }
  18. bool toposort()
  19. {
  20. t=n;
  21. memset(vis,0,sizeof(vis));
  22. for(int u=1;u<=n;u++)
  23. {
  24. if(!vis[u]){
  25. if(!Dfs(u)) return false;
  26. }
  27. }
  28. return true;
  29. }

裸的拓扑排序的题目:Uva10305 - Ordering Tasks

  1. /***
  2. *Uva10305拓扑排序
  3. *临接矩阵存图,Dfs搜索回溯
  4. ******/
  5. #include <stdio.h>
  6. #include <string.h>
  7. #define Max 120
  8. int t;
  9. int map[Max][Max];
  10. int vis[Max],topo[Max];
  11. int m,n;
  12. bool Dfs(int u)
  13. {
  14. vis[u]=-1;
  15. for(int v=1;v<=n;v++)
  16. {
  17. if(map[u][v])
  18. {
  19. if(vis[v]<0) {return false;}
  20. else if(!vis[v]&&!Dfs(v)) return false;
  21. }
  22. }
  23. vis[u] = 1;topo[--t]=u;
  24. return true;
  25. }
  26. bool toposort()
  27. {
  28. t=n;
  29. memset(vis,0,sizeof(vis));
  30. for(int u=1;u<=n;u++)
  31. {
  32. if(!vis[u]){
  33. if(!Dfs(u)) return false;
  34. }
  35. }
  36. return true;
  37. }
  38. int main()
  39. {
  40. while(~scanf("%d%d",&n,&m))
  41. {
  42. if(n==0&&m==0) break;
  43. memset(map,0,sizeof(map));
  44. for(int i=0;i<m;i++)
  45. {
  46. int a,b;
  47. scanf("%d%d",&a,&b);
  48. map[a][b]=1;
  49. }
  50. if(toposort())
  51. {
  52. bool ok=true;
  53. for(int i=0;i<n;i++)
  54. {
  55. if(ok) {printf("%d",topo[i]);ok=false;}
  56. else printf(" %d",topo[i]);
  57. }
  58. printf("\n");
  59. }
  60. else
  61. printf("No\n");
  62. }
  63. return 0;
  64. }

发表评论

表情:
评论列表 (有 0 条评论,459人围观)

还没有评论,来说两句吧...

相关阅读

    相关 拓扑排序

    拓扑排序是一张AOV网(Activity Of Vertex NetWork),并且是无环的网! 概念: 设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列V1,V

    相关 拓扑排序

    什么是拓扑排序? 在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序

    相关 拓扑排序

    拓 扑 排 序 一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动(activity)。在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就

    相关 拓扑排序

    (1)有向无环图 无环的有向图,简称 DAG (Directed Acycline Graph) 图。 有向无环图在工程计划和管理方面的应用:除最简单的情况之外,几

    相关 拓扑排序

    拓扑排序: 拓扑排序是根据离散数学中有关偏序与全序定义的。 ![0_1314168765l7fq.gif][] 若一个集合 X 上的关系 R 是自反的 反

    相关 拓扑排序

     一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动(activity)。在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就是说,一个子工程