题目概述
解题思路
分析这道题的意思,看上去是要我们判断一个有向图中是否存在环。判断图中是否存在环,可以采用拓扑排序方法。它的思路是:
- 首先,判断图中是否存在入度为零的节点;
- 然后,将所有入度为零的节点(记为)删除,并将从该节点出发的所有节点的入度减去1;
- 重复以上两步,直到图中不存在入度为零的节点。
- 这时,检查是否还有节点未被删除(也就是,是否存在入度不为零的节点),如果存在,则不符合拓扑排序的条件。
在实现上,我们可以用BFS/DFS遍历图,维护每个节点的邻接节点,同时记录每个节点的入度。
然后只要递归地去除这些入度为零的节点即可得到结果。
方法性能
设图中节点数为V,边数为E,则方法的时间复杂度为O(V+E)。
示例代码
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites)
{
vector<vector<int>> edges(numCourses);
int inside_num[10010];
queue<int> inside_zero;
memset(inside_num, 0, sizeof(inside_num));
for(int ei = 0; ei < prerequisites.size(); ++ei)
{
vector<int> Ei = prerequisites[ei];
for(int ni = 0; ni < Ei.size() - 1; ++ni)
{
edges[Ei[ni]].push_back(Ei[ni + 1]);
inside_num[Ei[ni + 1]]++;
}
}
//find rudu == 0
for(int ni = 0; ni < numCourses; ++ni)
{
if(inside_num[ni] == 0)
inside_zero.push(ni);
}
//check whether all nodes are zero rudu
while(!inside_zero.empty())
{
int temp = inside_zero.front();
inside_zero.pop();
for(int ei = 0, neigh; ei < edges[temp].size(); ++ei)
{
neigh = edges[temp][ei];
inside_num[neigh] -= 1;
if(inside_num[neigh] == 0)
inside_zero.push(neigh);
}
}
for(int i = 0; i < numCourses; ++i)
if(inside_num[i])
return false;
return true;
}
};
Tip:
- 二维vector的初始化,可以采用vector<vector<xxx>> name_of_v(length_of_v) 来实现。
- 拓扑排序可用于检查有向图中是否有环。