拓扑排序判断有向图中是否有环
拓扑排序的工程意义
拓扑排序是对一个有向图构造拓扑序列,解决工程是否能顺利进行的问题。构造时有 2 2 2种结果:
- 此图全部顶点被输出:说明说明图中无「环」存在, 是 AOV 网(有向无环图)
- 没有输出全部顶点:说明图中有「环」存在,不是 AOV 网
主要思想
遍历所有入度为 0 0 0的节点,并由该节点刷新其指向节点的度,即将其指向节点的入度减 1 1 1,当该节点入度为 0 0 0,将其加入队列。最后查看所有节点的入度是否为 0 0 0,如果全部为 0 0 0,说明该网络是有向无环图。
例题
LeetCode.207 课程表
你这个学期必须选修 n u m C o u r s e s numCourses numCourses门课程,记为 0 0 0到 n u m C o u r s e s − 1 numCourses-1 numCourses−1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 p r e r e q u i s i t e s prerequisites prerequisites 给出,其中 p r e r e q u i s i t e s [ i ] = [ a i , b i ] prerequisites[i] = [a_i, b_i] prerequisites[i]=[ai,bi],表示如果要学习课程 a i a_i ai则必须先学习课程 b i b_i bi。例如,先修课程对 [ 0 , 1 ] [0, 1] [0,1]表示:想要学习课程 0 0 0,你需要先完成课程 1 1 1 。 请你判断是否可能完成所有课程的学习?如果可以,返回 t r u e true true;否则,返回 f a l s e false false。 提示: 1 < = n u m C o u r s e s < = 1 0 5 1 <= numCourses <= 10^5 1<=numCourses<=105 0 < = p r e r e q u i s i t e s . l e n g t h < = 5000 0 <= prerequisites.length <= 5000 0<=prerequisites.length<=5000 p r e r e q u i s i t e s [ i ] . l e n g t h = = 2 prerequisites[i].length == 2 prerequisites[i].length==2 0 < = a i , b i < n u m C o u r s e s 0 <= a_i, b_i < numCourses 0<=ai,bi<numCourses p r e r e q u i s i t e s [ i ] prerequisites[i] prerequisites[i]中的所有课程对互不相同
思路
使用拓扑排序来解题,当构成的有向图没有环,那么说明可以完成所有课程的学习。先修课程数组相当于有向图的边,当课程不需要先修课程即可学习,那么该课程入度为 0 0 0,否则入度就是需要先修课程的数量。
代码
class Solution { public boolean canFinish(int n, int[][] edges) { int[] d = new int[n]; List<Integer>[] g = new List[n]; for(int i = 0; i < n; i++) { g[i] = new ArrayList<>(); } for(int[] x : edges) { int a = x[0], b = x[1]; g[b].add(a); d[a]++; } Queue<Integer> q = new LinkedList<>(); for(int i = 0; i < n; i++) { if(d[i] == 0) { q.offer(i); } } int cnt = 0; while(q.size() > 0) { int x = q.poll(); cnt++; for(int y : g[x]) { d[y]--; if(d[y] == 0) { q.offer(y); } } } return cnt == n; } }