拓扑排序 和leetcode 207. 课程表

1 拓扑排序

 拓扑排序主要是对有向无环图(DAG)进行拓扑排序。
在这里插入图片描述
 上图就是一个有向无环图,有向无环图常用来描述一个工程或系统的进行过程(通常把计划,施工,生产,程序流程等当成是一个工程)
 一个工程可以分为若干个子工程,只要完成了这些子工程(活动),就可以导致整个工程的完成。
 有向无环图有两个应用:
 AOV网(解决拓扑排序):用一个有向图表示一个工程的各子工程及其相互制约的关系,其中以顶点表示活动,弧表示活动之间的相互制约关系,称这种有向图为顶点表示的网。简称AOV网。
 AOE网(解决关键路径):用一个有向图表示一个工程的各子工程及其相互制约的关系,其中以弧表示活动,顶点表示活动之间的开始或结束事件,称这种有向图为边表示活动的网。简称AOE网。
 拓扑排序:在AOV网没有回路的前提下,我们将全部活动排列成一个线性序列,使得若AOV网中有弧<i,j>存在,则在这个序列中,i一定排在j的前面,具有这种性质的线性序列称为拓扑有序序列,相应的拓扑有序排序的算法就称为拓扑排序。
 方法:
1、在有向图中选一个没有前驱的顶点且输出
2、从图中删除该顶点和所有以它为尾的弧
3、重复上述两步,直到全部顶点均已输出;或者当图中不存在无前驱的顶点为止。(所以拓扑排序也可以检查图中是否有环)。
在这里插入图片描述
对于一个有向无环图,我们发现c1和C9是没有前驱节点的,所以任选一个,C1,随后删除该顶点和所有以它为尾的弧,如下图。
在这里插入图片描述
最后,重复这个过程,得到其拓扑排序为 C1 C2 C3 C4 C5 C7 C9 C10 C11 C6 C12 C8

2 课程表

你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
这里给出两个概念:图的入度和出度
入度就是:有向图的某个顶点作为终点的次数和。
出度就是:有向图的某个顶点作为起点的次数和。
思路:这个题一看就是遍历问题(能否学习完所有课程),就想到bfs,按照拓扑排序的思想,先将入度为0的节点删除,随后删除这个节点的所有出边,在循环。重点是我们要怎么初始化这个图,我们可以生成对应每个节点的入度和出边,然后套用bfs的模板就ok了。最后判断是可以学习完整个课程是利用一个count变量,我们在bfs时,每遍历一个元素,count++,最后判断count==numCourses。

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
       /*
       在每一个[1,0]中,prerequisite[0]是目的节点,prerequisite[1]是出发节点,
       记录每个节点的出度边
       记录每个节点的入度
       然后进行bfs
       */
       map<int,vector<int>> outedges;
       map<int,int> degree;
       for(auto prerequisite:prerequisites)
       {
           outedges[prerequisite[1]].push_back(prerequisite[0]);//记录每个节点的出度边
           degree[prerequisite[0]]++;
       }
       int count=0;
       queue<int> q;
       //将所有节点中,度为0的节点入队
       for(int i=0;i<numCourses;i++)
       {
           if(degree[i]==0)
               q.push(i);
       }
       while(!q.empty())
       {
           int tmp=q.front();
           q.pop();
           count++;
           for(auto next:outedges[tmp])
           {
               degree[next]--;
               if(degree[next]==0)
                    q.push(next);
           }
       }
       return count==numCourses;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值