《算法设计与分析》第三周作业

《算法设计与分析》第三周作业

标签(空格分隔): 课堂作业

姓名:李**
学号: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;
        
};

猜你喜欢

转载自blog.csdn.net/Ray0758/article/details/82825559