《算法设计与分析》第三周作业
标签(空格分隔): 课堂作业
姓名:李**
学号:16340114
题目:Course Schedule(https://leetcode.com/problems/course-schedule/description/)
注:本篇博客中所有图片均来自教科书Algorithms(Dasgupta),如有侵权,请联系博主删除图片。
题目概要
把题目翻译一下就是要判断一个有向图有没有环,也就是判断一个图是不是dag。
一开始的时候以为特简单,还说这怎么就是medium难度,不就是做一个深度搜索嘛
后来仔细想了想,深搜好像是判断连通与否的,不是判断有没有环的TAT
思路
思路一
将输入的有向图做一次拓扑排序,如果可以成功进行拓扑排序,即该有向图无环,如果不能进行拓扑排序,即该有向图有环。
思路二
第二种思想是应用教科书(Algorithms(Dasgupta))里的思想,把输入的有向图转换成DFS树,判断有无回边(backedge)即可判断该图是不是dag。
Property A directed graph has a cycle if and only if its depth-first search reveals a backedge.
具体实现
首先将输入的边链表(edge list)转换成邻接表(Adjacency lists)。按照书本的方法,进行一次深度搜索,对节点进行preVisit与postVisit时打上clock标记(具体请看教材第三章)。深度搜索完成后,按照下图,检测图有没有回边,输出结果,完成。
心得
现学现用真爽。
源码:
class Solution
{
public:
Solution()
{
clock = 1;
}
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites)
{
//handle input
for (int i = 0; i < prerequisites.size(); ++i)
{
int u = prerequisites[i].first;
int v = prerequisites[i].second;
vertex.insert(u);
vertex.insert(v);
if (edges.find(u) != edges.end())
{
edges[u].insert(v);
}
else
{
set<int> nextVertice;
nextVertice.insert(v);
edges[u] = nextVertice;
}
}
//pre handle
for (auto currentVertice : vertex)
{
visited[currentVertice] = false;
}
//dfs
for (auto currentVertice : vertex)
{
visit(currentVertice);
}
//check backedge
for (int i = 0; i < prerequisites.size(); ++i)
{
int u = prerequisites[i].first;
int v = prerequisites[i].second;
cout << "u " << preClock[u] << " : " << postClock[u] << endl;
cout << "v " << preClock[v] << " : " << postClock[v] << endl << endl;
if (preClock[v] < preClock[u] && postClock[v] > postClock[u])
{
//has backedge
return false;
}
}
return true;
}
void preVisit(int currentVertice)
{
preClock[currentVertice] = clock;
clock++;
}
void postVisit(int currentVertice)
{
postClock[currentVertice] = clock;
clock++;
}
void visit(int currentVertice)
{
if (visited[currentVertice])
return;
visited[currentVertice] = true;
preVisit(currentVertice);
for (auto nextVertice : edges[currentVertice])
{
visit(nextVertice);
}
postVisit(currentVertice);
}
private:
int clock;
map<int, int> preClock;
map<int, int> postClock;
map<int, bool> visited;
map< int, set<int> > edges;
set< int > vertex;
};