207. Course Schedule My SubmissionsQuestionEditorial Solution【M】【48】【vip】【再来一遍】

175 篇文章 0 订阅
157 篇文章 0 订阅

There are a total of n courses you have to take, labeled from 0 to n - 1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

For example:

2, [[1,0]]

There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.

2, [[1,0],[0,1]]

There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.

Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.

click to show more hints.

Hints:
  1. This problem is equivalent to finding if a cycle exists in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
  2. Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
  3. Topological sort could also be done via BFS.


Subscribe to see which companies asked this question




这道题等价于判断有向图里有没有环。


有向图:

主要有深度优先和拓扑排序2中方法

 1、拓扑排序,如果能够用拓扑排序完成对图中所有节点的排序的话,就说明这个图中没有环,而如果不能完成,则说明有环。

    2、可以用Strongly Connected Components来做,我们可以回忆一下强连通子图的概念,就是说对于一个图的某个子图,该子图中的任意u->v,必有v->u,则这是一个强连通子图。这个限定正好是环的概念。所以我想,通过寻找图的强连通子图的方法应该可以找出一个图中到底有没有环、有几个环。

    3、就是用一个改进的DFS

    刚看到这个问题的时候,我想单纯用DFS就可以解决问题了。但细想一下,是不能够的。如果题目给出的是一个无向图,那么OK,DFS是可以解决的。但无向图得不出正确结果的。比如:A->B,A->C->B,我们用DFS来处理这个图,我们会得出它有环,但其实没有。

    我们可以对DFS稍加变化,来解决这个问题。解决的方法如下:

    图中的一个节点,根据其C[N]的值,有三种状态:

    0,此节点没有被访问过

    -1,被访问过至少1次,其后代节点正在被访问中

    1,其后代节点都被访问过。

    按照这样的假设,当按照DFS进行搜索时,碰到一个节点时有三种可能:

    1、如果C[V]=0,这是一个新的节点,不做处理

    2、如果C[V]=-1,说明是在访问该节点的后代的过程中访问到该节点本身,则图中有环。

    3、如果C[V]=1,类似于2的推导,没有环。    在程序中加上一些特殊的处理,即可以找出图中有几个环,并记录每个环的路径


拓扑排序

   该DAG的拓扑序列为A B C D或者A C B D

 而此有向图是不存在拓扑序列的,因为图中存在环路

二.拓扑序列算法思想

 (1)从有向图中选取一个没有前驱(即入度为0)的顶点,并输出之;

 
 (2)从有向图中删去此顶点以及所有以它为开始的弧;
     重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。





check2是通过的做法
主函数里的是拓扑排序
check1是超时的



class Solution(object):
    def canFinish(self, numCourses, prerequisites):

        n = numCourses
        p = prerequisites
        v = [0] * n
        dic = {}
        indegree = [0] * n

        graph = [[] for i in xrange(n)]#[[]] * n
        for i,j in p:
            graph[i].append(j)

        #print graph

        def check2(cur):
            if v[cur] == -1:
                return False
            if v[cur] == 1:#如果访问到这儿,后面的节点之前都已经访问过了,没问题,所以等于一个剪枝的过程
                return True
            v[cur] = -1
            #l = dic.get(cur,[])
            for j in graph[cur]:
                if not check2(j):
                    return False
            v[cur] = 1
            return True

        for i in xrange(n):
            if not check2(i):
                return False
        return True

        '''
        def check(cur):
            if v[cur] == 1:
                return True
            v[cur] = 1
            l = dic.get(cur)
            if l != None:
                for i in l:
                    if check(i):
                        return True
            v[cur] = 0
            return False

        for i in p:
            dic[i[0]] = dic.get(i[0],[]) + [i[1]]
            indegree[i[1]] += 1

        q = []
        for i in xrange(len(indegree)):
            if indegree[i] == 0:
                q += i,
        #print q
        while q != []:
            node = q.pop()
            for i,j in p:
                #print i,j,node
                if i == node:
                    indegree[j] -= 1
                    if indegree[j] == 0:
                        q += j,
        #print indegree
        return sum(indegree)  == 0
        '''



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值