1. 程式人生 > >《演算法設計與分析》第三週作業

《演算法設計與分析》第三週作業

《演算法設計與分析》第三週作業

標籤(空格分隔): 課堂作業

文章目錄

姓名:李**
學號: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; };