Problem
给定一个有向图,判断该有向图是否无环。
图的表示是一个整数n和一个pair为元素的向量。整数n表示点的个数。
Example
edges={[0,1],[1,0]},n=2
return false
edges={[0,1],[1,2],[2,3]},n=4
return true
Algorithm
判断图是否无环。
想到一个利用入度来操作的做法,类似于拓扑排序。具体实现利用队列来完成。
- 先统计图中每个点的入度
- 将图中所有入度为0的点加入队列
- 若队列非空,重复以下过程:
- 取出队首,将与队首相邻的所有点入度减一;若减一后入度为0,则加入队列
- 重复以上过程直到队列为空,若此时图中仍存在入度不为0的点,则说明原图有环;若不存在入度为0的点,则说明原图无环。
考试时第一时间想到了曾经在LeetCode上写过的题目。原题是 LeetCode #207 - Course Schedule - Medium:http://blog.youkuaiyun.com/arcome/article/details/53790947
考试时候也是按照这里的思路来写,但是提交的结果是超时。超时的代码如下。
class Solution {
public:
bool noCircle(int n, vector<pair<int, int>>& edges) {
vector<int> in(n,0);
for(int i=0;i<edges.size();i++){
in[edges[i].first]++;
}
queue<int> q;
for(int i=0;i<in.size();i++){
if(in[i]==0) q.push(i);
}
while(!q.empty()){
int p=q.front();
q.pop();
int t;
for(int i=0;i<edges.size();i++){
if(edges[i].first==p){
t=edges[i].second
in[t]--;
if(in[t]==0) q.push(t);
}
}
}
for(int i=0;i<in.size();i++){
if(in[i]!=0) return false;
}
return true;
}
};
后来对比LeetCode题目的AC代码,发现LeetCode的代码多加了一个二维向量graph来存每个节点相邻的点。这样的话在队列中对相邻点的入度操作时便可以避开遍历所有边,有效地减小的时间复杂度。可惜考试的时候没有考虑到这一点,目测这个思路就是原题的正确解法。
代码如下。
class Solution {
public:
bool noCircle(int n, vector<pair<int, int>>& edges) {
vector<vector<int>> graph(n,vector<int> (0));
vector<int> in(n,0);
for(int i=0;i<edges.size();i++){
graph[edges[i].second].push_back(edges[i].first);
in[edges[i].first]++;
}
queue<int> q;
for(int i=0;i<in.size();i++){
if(in[i]==0) q.push(i);
}
while(!q.empty()){
int p=q.front();
q.pop();
for(int i=0;i<graph[p].size();i++){
in[graph[p][i]]--;
if(in[graph[p][i]]==0) q.push(graph[p][i]);
}
}
for(int i=0;i<in.size();i++){
if(in[i]!=0) return false;
}
return true;
}
};