拓扑排序判断有向图中是否有环

这篇博客探讨了拓扑排序在解决课程先修关系问题中的重要作用。通过拓扑排序,可以判断是否存在课程的先修环,从而确定是否可能完成所有课程的学习。在LeetCode的207课程表问题中,利用拓扑排序方法,当图中不存在环时,表明课程顺序可安排,反之则无法完成。文章详细阐述了拓扑排序的思路和代码实现,展示了如何运用此算法解决实际问题。

拓扑排序的工程意义

拓扑排序是对一个有向图构造拓扑序列,解决工程是否能顺利进行的问题。构造时有222种结果:

  1. 此图全部顶点被输出:说明说明图中无「环」存在, 是 AOV 网(有向无环图)
  2. 没有输出全部顶点:说明图中有「环」存在,不是 AOV 网

主要思想

遍历所有入度为000的节点,并由该节点刷新其指向节点的度,即将其指向节点的入度减111,当该节点入度为000,将其加入队列。最后查看所有节点的入度是否为000,如果全部为000,说明该网络是有向无环图。

例题

LeetCode.207 课程表

你这个学期必须选修numCoursesnumCoursesnumCourses门课程,记为000numCourses−1numCourses-1numCourses1
在选修某些课程之前需要一些先修课程。 先修课程按数组prerequisitesprerequisitesprerequisites 给出,其中prerequisites[i]=[ai,bi]prerequisites[i] = [a_i, b_i]prerequisites[i]=[ai,bi],表示如果要学习课程aia_iai则必须先学习课程bib_ibi。例如,先修课程对[0,1][0, 1][0,1]表示:想要学习课程000,你需要先完成课程111
请你判断是否可能完成所有课程的学习?如果可以,返回truetruetrue;否则,返回falsefalsefalse
提示
1<=numCourses<=1051 <= numCourses <= 10^51<=numCourses<=105
0<=prerequisites.length<=50000 <= prerequisites.length <= 50000<=prerequisites.length<=5000
prerequisites[i].length==2prerequisites[i].length == 2prerequisites[i].length==2
0<=ai,bi<numCourses0 <= a_i, b_i < numCourses0<=ai,bi<numCourses
prerequisites[i]prerequisites[i]prerequisites[i]中的所有课程对互不相同

思路

使用拓扑排序来解题,当构成的有向图没有环,那么说明可以完成所有课程的学习。先修课程数组相当于有向图的边,当课程不需要先修课程即可学习,那么该课程入度为000,否则入度就是需要先修课程的数量。

代码

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值