拓扑排序问题。

class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        int Hash[10010];//每个节点的入度
        vector<vector<int>> v(numCourses);//用于存储每个节点相邻的边
        stack<int> s;//存放入度为0的节点
    memset(Hash, 0, sizeof(Hash));
    for(int i =0 ; i < prerequisites.size();i++){
        pair<int, int>p = prerequisites[i];
        int x = p.first;
        int y = p.second;
        cout<<"x = "<<x <<"y = "<<y<<endl;
        v[x].push_back(y);
        ++Hash[y];
    }
    for(int i = 0; i < numCourses; i++){
        if(Hash[i] == 0){
            s.push(i);
        }
    }
    while (!s.empty()) {
        int cur = s.top();//找到入度为0的点
        s.pop();
        for(int i = 0; i < prerequisites.size(); i++){
            pair<int, int>p = prerequisites[i];
            int x = p.first;
            int y = p.second;
            if(cur == x){
                for(int j = 0; j < v[cur].size(); j++){
                    --Hash[v[cur][j]];//删除以该点为起点的所有有向边
                    if(Hash[v[cur][j]] == 0)
                        s.push(v[cur][j]);
                }
                break;
            }
        }
    }
    for(int i = 0; i < numCourses; i++){
        if(Hash[i] != 0)
            return false;
    }
    return true;
    }
};

 

补充一个python的实现:

 1 class Solution:
 2     #返回True表示有环,返回False表示无环
 3     def dfs(self,visited,memo,dic,i):
 4         if visited[i]:
 5             return True
 6         if memo[i] == 0:
 7             return False
 8         elif memo[i] == 1:
 9             return True
10         for cs in dic[i]:
11             visited[i] = True
12             bl = self.dfs(visited,memo,dic,cs)
13             visited[i] = False
14             if bl:
15                 #当前线路中出现了环,则标记当前课程为1,返回True
16                 memo[i] = 1
17                 return True
18         ##当前线路,已经找到最早的前置课程,没有出现"",则标记为0,表示课程i是可以学习的
19         memo[i] = 0
20         return False#返回False表示无环,当前课程i,可以完成学习
21 
22     def canFinish(self, numCourses: 'int', prerequisites: 'List[List[int]]') -> 'bool':
23         dic = {}
24         n = len(prerequisites)
25         for i in range(numCourses):
26             dic[i] = []
27         for i in range(n):
28             cs = prerequisites[i][0]#当前课程
29             pre = prerequisites[i][1]#前置课程
30             dic[cs].append(pre)
31         visited = [False for _ in range(numCourses)]
32         memo = [-1 for _ in range(numCourses)]
33         for i in range(numCourses):
34             #只要出现过一个有环的线路,则不能符合题目"所有课程都完成"的目标
35             if self.dfs(visited,memo,dic,i):
36                 return False
37         return True

算法思路:深度优先遍历,判断图中是否有环。

使用两个标记数组:

visited=True表示当前“线路”上的节点已经被锁定,如果在线路遍历的过程中遇到已经被锁定的节点,那说明遇到了环。

memo表示备忘录(缓存),默认状态为-1,标记为0表示本节点不存在环,标记为1表示本节点有环,使用备忘录可加速得到查询结果。

posted on 2018-10-06 09:48  Sempron2800+  阅读(167)  评论(0编辑  收藏  举报