<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>directed graph Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/directed-graph/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/directed-graph/</link>
	<description></description>
	<lastBuildDate>Mon, 30 Sep 2019 04:42:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.8</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>directed graph Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/directed-graph/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 802. Find Eventual Safe States</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-802-find-eventual-safe-states/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-802-find-eventual-safe-states/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 18 Mar 2018 06:37:10 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[cycle]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[directed graph]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[topological sort]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2196</guid>

					<description><![CDATA[<p>Problem https://leetcode.com/problems/find-eventual-safe-states/description/ 题目大意：给一个有向图，找出所有不可能进入环的节点。 In a directed graph, we start at some node and every turn, walk along a directed edge of the graph.  If we&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-802-find-eventual-safe-states/">花花酱 LeetCode 802. Find Eventual Safe States</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/v5Ni_3bHjzk?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1>Problem</h1>
<p><a href="https://leetcode.com/problems/find-eventual-safe-states/description/">https://leetcode.com/problems/find-eventual-safe-states/description/</a></p>
<p>题目大意：给一个有向图，找出所有不可能进入环的节点。</p>
<p>In a directed graph, we start at some node and every turn, walk along a directed edge of the graph.  If we reach a node that is terminal (that is, it has no outgoing directed edges), we stop.</p>
<p>Now, say our starting node is <em>eventually safe </em>if and only if we must eventually walk to a terminal node.  More specifically, there exists a natural number <code>K</code> so that for any choice of where to walk, we must have stopped at a terminal node in less than <code>K</code> steps.</p>
<p>Which nodes are eventually safe?  Return them as an array in sorted order.</p>
<p>The directed graph has <code>N</code> nodes with labels <code>0, 1, ..., N-1</code>, where <code>N</code> is the length of <code>graph</code>.  The graph is given in the following form: <code>graph[i]</code> is a list of labels <code>j</code> such that <code>(i, j)</code> is a directed edge of the graph.</p>
<pre class="crayon:false "><strong>Example:</strong>
<strong>Input:</strong> graph = [[1,2],[2,3],[5],[0],[5],[],[]]
<strong>Output:</strong> [2,4,5,6]
Here is a diagram of the above graph.

</pre>
<p><img src="https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png" alt="Illustration of graph" /></p>
<p><strong>Note:</strong></p>
<ul>
<li><code>graph</code> will have length at most <code>10000</code>.</li>
<li>The number of edges in the graph will not exceed <code>32000</code>.</li>
<li>Each <code>graph[i]</code> will be a sorted list of different integers, chosen within the range <code>[0, graph.length - 1]</code>.</li>
</ul>
<h1><strong>Idea: Finding Cycles</strong></h1>
<p><img class="alignnone size-full wp-image-2214" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/802-ep174.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/802-ep174.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/802-ep174-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/802-ep174-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1><strong>Solution 1: DFS</strong></h1>
<p><strong> </strong>A node is safe if and only if: itself and all of its neighbors do not have any cycles.</p>
<p>Time complexity: O(V + E)</p>
<p>Space complexity: O(V + E)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 155 ms
class Solution {
public:
  vector&lt;int&gt; eventualSafeNodes(vector&lt;vector&lt;int&gt;&gt;&amp; graph) {    
    vector&lt;State&gt; states(graph.size(), UNKNOWN);
    vector&lt;int&gt; ans;
    for (int i = 0; i &lt; graph.size(); ++i)      
      if (dfs(graph, i, states) == SAFE)
        ans.push_back(i);
    return ans;
  }
private:
  enum State {UNKNOWN, VISITING, SAFE, UNSAFE};
  State dfs(const vector&lt;vector&lt;int&gt;&gt;&amp; g, int cur, vector&lt;State&gt;&amp; states) {
    if (states[cur] == VISITING)
      return states[cur] = UNSAFE;
    if (states[cur] != UNKNOWN)
      return states[cur];
    states[cur] = VISITING;
    for (int next : g[cur])
      if (dfs(g, next, states) == UNSAFE) 
        return states[cur] = UNSAFE;
    return states[cur] = SAFE;
  }
};</pre><p></p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-207-course-schedule/">[解题报告] LeetCode 207. Course Schedule</a></li>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-210-course-schedule-ii/">花花酱 LeetCode 210. Course Schedule II</a></li>
<li><a href="http://zxi.mytechroad.com/blog/tree/leetcode-684-redundant-connection/">[解题报告] LeetCode 684. Redundant Connection 花花酱</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-802-find-eventual-safe-states/">花花酱 LeetCode 802. Find Eventual Safe States</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-802-find-eventual-safe-states/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 210. Course Schedule II</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-210-course-schedule-ii/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-210-course-schedule-ii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 14 Dec 2017 06:35:21 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[Medium]]></category>
		<category><![CDATA[cycle]]></category>
		<category><![CDATA[directed graph]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[topological sort]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1228</guid>

					<description><![CDATA[<p>Problem There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prerequisites, for example to take course 0&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-210-course-schedule-ii/">花花酱 LeetCode 210. Course Schedule II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/Qqgck2ijUjU?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>There are a total of <i>n</i> courses you have to take, labeled from <code>0</code> to <code>n - 1</code>.</p>
<p>Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: <code>[0,1]</code></p>
<p>Given the total number of courses and a list of prerequisite <b>pairs</b>, return the ordering of courses you should take to finish all courses.</p>
<p>There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.</p>
<p>For example:</p><pre class="crayon-plain-tag">2, [[1,0]]</pre><p>There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is <code>[0,1]</code></p><pre class="crayon-plain-tag">4, [[1,0],[2,0],[3,1],[3,2]]</pre><p>There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. So one correct course order is <code>[0,1,2,3]</code>. Another correct ordering is<code>[0,2,1,3]</code>.</p>
<p><b>Note:</b></p>
<ol>
<li>The input prerequisites is a graph represented by <b>a list of edges</b>, not adjacency matrices. Read more about <a href="https://www.khanacademy.org/computing/computer-science/algorithms/graph-representation/a/representing-graphs" target="_blank" rel="noopener">how a graph is represented</a>.</li>
<li>You may assume that there are no duplicate edges in the input prerequisites.</li>
</ol>
<p><strong>题目大意：</strong></p>
<p>给你一些课程和它的先修课程，让你输出修课顺序。如果无法修完所有课程，返回空数组。</p>
<p><ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
<p><img class="alignnone size-full wp-image-1252" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/210-ep133.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/210-ep133.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/210-ep133-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/210-ep133-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1><strong>Idea</strong></h1>
<p>Topological sorting</p>
<p>拓扑排序</p>
<h1><strong>Solution 1: Topological Sorting</strong></h1>
<p>Time complexity: O(V+E)</p>
<p>Space complexity: O(V+E)</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 16 ms
class Solution {
public:
  vector&lt;int&gt; findOrder(int numCourses, vector&lt;pair&lt;int, int&gt;&gt;&amp; prerequisites) {
    vector&lt;vector&lt;int&gt;&gt; graph(numCourses);    
    for(const auto&amp; p : prerequisites)
      graph[p.second].push_back(p.first);

    // states: 0 = unkonwn, 1 == visiting, 2 = visited
    vector&lt;int&gt; v(numCourses, 0);
    vector&lt;int&gt; ans;
    
    for (int i = 0; i &lt; numCourses; ++i)
      if (dfs(i, graph, v, ans)) return {};

    std::reverse(ans.begin(), ans.end());
    return ans;
  }
private:
  bool dfs(int cur, vector&lt;vector&lt;int&gt;&gt;&amp; graph, vector&lt;int&gt;&amp; v, vector&lt;int&gt;&amp; ans) {
    if (v[cur] == 1) return true;
    if (v[cur] == 2) return false;

    v[cur] = 1;
    
    for (const int t : graph[cur])
      if (dfs(t, graph, v, ans)) return true;
    
    v[cur] = 2;
    ans.push_back(cur);

    return false;
  }
};</pre><p></div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 83 ms
class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        ArrayList&lt;ArrayList&lt;Integer&gt;&gt; graph = new ArrayList&lt;&gt;();
        
        for (int i = 0; i &lt; numCourses; ++i)
            graph.add(new ArrayList&lt;Integer&gt;());
        
        for (int i = 0; i &lt; prerequisites.length; ++i) {
            int course = prerequisites[i][0];
            int prerequisite = prerequisites[i][1];            
            graph.get(course).add(prerequisite);
        }
        
        int[] visited = new int[numCourses];
        List&lt;Integer&gt; ans = new ArrayList&lt;Integer&gt;();
        Integer index = numCourses;
        for (int i = 0; i &lt; numCourses; ++i)
            if (dfs(i, graph, visited, ans)) return new int[0];        
        
        return ans.stream().mapToInt(i-&gt;i).toArray();
    }
    
    private boolean dfs(int curr, ArrayList&lt;ArrayList&lt;Integer&gt;&gt; graph, int[] visited, List&lt;Integer&gt; ans) {
        if (visited[curr] == 1) return true;
        if (visited[curr] == 2) return false;
        
        visited[curr] = 1;
        for (int next : graph.get(curr))
            if (dfs(next, graph, visited, ans)) return true;
        
        visited[curr] = 2;
        ans.add(curr);
        
        return false;
    }    
}</pre><p></div></div></p>
<h1><strong>Related Problems:</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-207-course-schedule/">[解题报告] LeetCode 207. Course Schedule</a></li>
<li><a href="https://zxi.mytechroad.com/blog/graph/leetcode-802-find-eventual-safe-states/">花花酱 LeetCode 802. Find Eventual Safe States</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-210-course-schedule-ii/">花花酱 LeetCode 210. Course Schedule II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-210-course-schedule-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 207. Course Schedule</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-207-course-schedule/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-207-course-schedule/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 21 Oct 2017 06:26:36 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[Medium]]></category>
		<category><![CDATA[cycle]]></category>
		<category><![CDATA[directed graph]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[topological sort]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=654</guid>

					<description><![CDATA[<p>Problem: There are a total of&#160;n&#160;courses you have to take, labeled from&#160;0&#160;to&#160;n - 1. Some courses may have prerequisites, for example to take course 0&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-207-course-schedule/">花花酱 LeetCode 207. Course Schedule</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/M6SBePBMznU?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>There are a total of&nbsp;<i>n</i>&nbsp;courses you have to take, labeled from&nbsp;<code>0</code>&nbsp;to&nbsp;<code>n - 1</code>.</p>
<p>Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair:&nbsp;<code>[0,1]</code></p>
<p>Given the total number of courses and a list of prerequisite&nbsp;<b>pairs</b>, is it possible for you to finish all courses?</p>
<p>For example:</p><pre class="crayon-plain-tag">2, [[1,0]]</pre><p>There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.</p><pre class="crayon-plain-tag">2, [[1,0],[0,1]]</pre><p>There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.</p>
<p><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script><br />
     (adsbygoogle = window.adsbygoogle || []).push({});<br />
</script></p>
<p><strong>Idea:</strong></p>
<p>Finding cycles O(n^2) -&gt; Topological sort O(n)</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93.png"><img class="alignnone size-full wp-image-659" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-1.png"><img class="alignnone size-full wp-image-658" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/207-ep93-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<h1><strong>Solution 1: Topological Sort</strong></h1>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Time complexity: O(n)
// Runtime: 12 ms
class Solution {
public:
    bool canFinish(int numCourses, vector&lt;pair&lt;int, int&gt;&gt;&amp; prerequisites) {
        
        graph_ = vector&lt;vector&lt;int&gt;&gt;(numCourses);
        
        for(const auto&amp; p : prerequisites)
            graph_[p.first].push_back(p.second);
        
        // states: 0 = unkonwn, 1 == visiting, 2 = visited
        vector&lt;int&gt; v(numCourses, 0);
        
        for(int i = 0; i &lt; numCourses; ++i)
            if(dfs(i, v)) return false;
        
        return true;
    }
    
private:
    vector&lt;vector&lt;int&gt;&gt; graph_;
    bool dfs(int cur, vector&lt;int&gt;&amp; v) {
        if(v[cur] == 1) return true;
        if(v[cur] == 2) return false;
        
        v[cur] = 1;
        
        for(const int t : graph_[cur])
            if(dfs(t, v)) return true;
        
        v[cur] = 2;
        
        return false;
    }
};</pre><p></div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 6 ms
// HashMap is slower than ArrayList in this problem.
class Solution {    
    public boolean canFinish(int numCourses, int[][] prerequisites) {        
        ArrayList&lt;ArrayList&lt;Integer&gt;&gt; graph = new ArrayList&lt;&gt;();
        
        for (int i = 0; i &lt; numCourses; ++i)
            graph.add(new ArrayList&lt;Integer&gt;());
        
        for (int i = 0; i &lt; prerequisites.length; ++i) {
            int course = prerequisites[i][0];
            int prerequisite = prerequisites[i][1];            
            graph.get(course).add(prerequisite);
        }
        
        int[] visited = new int[numCourses];
        for (int i = 0; i &lt; numCourses; ++i)
            if (dfs(i, graph, visited)) return false;
        
        return true;
    }
    
    private boolean dfs(int curr, ArrayList&lt;ArrayList&lt;Integer&gt;&gt; graph, int[] visited) {
        if (visited[curr] == 1) return true;
        if (visited[curr] == 2) return false;
        
        visited[curr] = 1;
                
        for (int next : graph.get(curr))
            if (dfs(next, graph, visited)) return true;
        
        visited[curr] = 2;
        return false;
    }

}</pre><p></div></div></p>
<p><script async="" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-fb+5w+4e-db+86" data-ad-client="ca-pub-2404451723245401" data-ad-slot="2162692788"></ins><br />
<script><br />
     (adsbygoogle = window.adsbygoogle || []).push({});<br />
</script></p>
<h1><strong>Solution 2: DFS&nbsp;Finding cycles</strong></h1>
<p>Time complexity: O(n^2)</p>
<p>Space complexity: O(n)</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Time complexity: O(n^2)
// Runtime: 179 ms
class Solution {
public:
    bool canFinish(int numCourses, vector&lt;pair&lt;int, int&gt;&gt;&amp; prerequisites) {
        
        graph_.clear();
        
        for(const auto&amp; p : prerequisites)
            graph_[p.first].insert(p.second);
        
        for (int i = 0; i &lt; numCourses; ++i) {
            vector&lt;int&gt; visited(numCourses, 0);
            if (cycle(i, i, visited)) return false;
        }
        
        return true;
    }
    
private:
    unordered_map&lt;int, unordered_set&lt;int&gt;&gt; graph_;
    
    bool cycle(int start, int curr, vector&lt;int&gt;&amp; visited) {        
        if (curr == start &amp;&amp; visited[start]) return true;
        if (!graph_.count(curr)) return false;
        
        for (const int next : graph_.at(curr)) {
            if (visited[next]) continue;
            visited[next] = true;
            if (cycle(start, next, visited)) return true;
        }
        return false;
    }
};</pre><p></div></div></p>
<h1><strong>Related Pr0blems:</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-210-course-schedule-ii/">花花酱 LeetCode 210. Course Schedule II</a></li>
<li><a href="https://zxi.mytechroad.com/blog/graph/leetcode-802-find-eventual-safe-states/">花花酱 LeetCode 802. Find Eventual Safe States</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-207-course-schedule/">花花酱 LeetCode 207. Course Schedule</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-207-course-schedule/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 685. Redundant Connection II</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-685-redundant-connection-ii/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-685-redundant-connection-ii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 07 Oct 2017 17:32:44 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[cycle]]></category>
		<category><![CDATA[directed graph]]></category>
		<category><![CDATA[union find]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=546</guid>

					<description><![CDATA[<p>Problem: In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) for which all other nodes are descendants&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-685-redundant-connection-ii/">花花酱 LeetCode 685. Redundant Connection II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/lnmJT5b4NlM?feature=oembed" frameborder="0" gesture="media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>In this problem, a rooted tree is a <b>directed</b> graph such that, there is exactly one node (the root) for which all other nodes are descendants of this node, plus every node has exactly one parent, except for the root node which has no parents.</p>
<p>The given input is a directed graph that started as a rooted tree with N nodes (with distinct values 1, 2, &#8230;, N), with one additional directed edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed.</p>
<p>The resulting graph is given as a 2D-array of <code>edges</code>. Each element of <code>edges</code> is a pair <code>[u, v]</code> that represents a <b>directed</b> edge connecting nodes <code>u</code> and <code>v</code>, where <code>u</code> is a parent of child <code>v</code>.</p>
<p>Return an edge that can be removed so that the resulting graph is a rooted tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array.</p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given directed graph will be like this:
  1
 / \
v   v
2--&amp;gt;3</pre><p><b>Example 2:</b></p><pre class="crayon-plain-tag">Input: [[1,2], [2,3], [3,4], [4,1], [1,5]]
Output: [4,1]
Explanation: The given directed graph will be like this:
5 &amp;lt;- 1 -&amp;gt; 2
     ^    |
     |    v
     4 &amp;lt;- 3</pre><p><b>Note:</b></p>
<p>&nbsp;</p>
<ul>
<li>The size of the input 2D-array will be between 3 and 1000.</li>
<li>Every integer represented in the 2D-array will be between 1 and N, where N is the size of the input array.</li>
</ul>
<p><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
<p><strong>Idea: </strong></p>
<p>Union Find</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/685-ep83.png"><img class="alignnone size-full wp-image-548" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/685-ep83.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/685-ep83.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/685-ep83-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/685-ep83-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/685-ep83-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><strong>Time complexity</strong>: O(nlog*n) ~ O(n)</p>
<p><strong>Space complexity</strong>: O(n)</p>
<p><strong>Solution:</strong></p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 6 ms
class Solution {
public:
    vector&lt;int&gt; findRedundantDirectedConnection(vector&lt;vector&lt;int&gt;&gt;&amp; edges) {
        
        vector&lt;int&gt; parents(edges.size() + 1, 0);
        vector&lt;int&gt; roots(edges.size() + 1, 0);       
        vector&lt;int&gt; sizes(edges.size() + 1, 1);
        
        vector&lt;int&gt; ans1;
        vector&lt;int&gt; ans2;
        
        for(auto&amp; edge: edges) {
            int u = edge[0];
            int v = edge[1];
            
            // A node has two parents
            if (parents[v] &gt; 0) {
                ans1 = {parents[v], v};
                ans2 = edge;
                
                // Delete the later edge
                edge[0] = edge[1] = -1;
            }
            
            parents[v] = u;
        }
        
        for(const auto&amp; edge: edges) {
            int u = edge[0];
            int v = edge[1];
            
            // Invalid edge (we deleted in step 1)
            if (u &lt; 0 || v &lt; 0) continue;
            
            if (!roots[u]) roots[u] = u;
            if (!roots[v]) roots[v] = v;
            int pu = find(u, roots);
            int pv = find(v, roots);
            
            // Both u and v are already in the tree
            if (pu == pv)
                return ans1.empty() ? edge : ans1;
            
            // Unoin, always merge smaller set (pv) to larger set (pu)
            if (sizes[pv] &gt; sizes[pu])
                swap(pu, pv);
            
            roots[pv] = pu;
            sizes[pu] += sizes[pv];
        }
        
        return ans2;
    }
    
private:
    int find(int node, vector&lt;int&gt;&amp; roots) {
        while (roots[node] != node) {
            roots[node] = roots[roots[node]];
            node = roots[node];
        }
        return node;
    }
};</pre><p>&nbsp;</p>
<p>C++ / without using Union find</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 6 ms
class Solution {
public:
    vector&lt;int&gt; findRedundantDirectedConnection(vector&lt;vector&lt;int&gt;&gt;&amp; edges) {
        
        vector&lt;int&gt; parents(edges.size() + 1, 0);        
        
        vector&lt;int&gt; ans1;
        vector&lt;int&gt; ans2;        
        
        bool dup_parents = false;
        
        for(auto&amp; edge: edges) {
            int u = edge[0];
            int v = edge[1];
            
            // A node has two parents
            if (parents[v] &gt; 0) {
                ans1 = {parents[v], v};
                ans2 = edge;
                dup_parents = true;
                // Delete the later edge
                edge[0] = edge[1] = -1;
            } else {            
                parents[v] = u;
            }
        }
        
        // Reset parents
        parents = vector&lt;int&gt;(edges.size() + 1, 0);
        
        for(const auto&amp; edge: edges) {
            int u = edge[0];
            int v = edge[1];
            
            // Invalid edge (we deleted in step 1)
            if (u &lt; 0 || v &lt; 0) continue;
            
            parents[v] = u;
            
            if (cycle(v, parents))
                return dup_parents ? ans1 : edge;
        }
        
        return ans2;
    }    
private:
    bool cycle(int v, const vector&lt;int&gt;&amp; parents) {
        int u = parents[v];        
        while (u) {
            if (u == v) return true;            
            u = parents[u];
        }
        return false;
    }
};</pre><p>&nbsp;</p>
<p>Python</p><pre class="crayon-plain-tag">"""
Author: Huahua
Runtime: 62 ms
"""
class Solution:
    def findRedundantDirectedConnection(self, edges):
        def cycle(v, p):
            u = p[v]
            while u != 0:
                if u == v: return True
                u = p[u]
            return False
        
        n = len(edges)
        p = [0] * (n + 1)
        
        ans1 = []
        ans2 = []
        dup_p = False
        
        for e in edges:
            u, v = e
            if p[v] &gt; 0:
                ans1 = [p[v], v]
                ans2 = [u, v]
                dup_p = True
                e[0] = e[1] = -1
            else:
                p[v] = u
        
        p = [0] * (n + 1)
        
        for u, v in edges:
            if u &lt; 0: continue
            p[v] = u
            if cycle(v, p):
                return ans1 if dup_p else [u, v]
        
        return ans2</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-685-redundant-connection-ii/">花花酱 LeetCode 685. Redundant Connection II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-685-redundant-connection-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
