<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://indianpedia.org/index.php?action=history&amp;feed=atom&amp;title=Kosaraju%27s_algorithm</id>
	<title>Kosaraju&#039;s algorithm - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://indianpedia.org/index.php?action=history&amp;feed=atom&amp;title=Kosaraju%27s_algorithm"/>
	<link rel="alternate" type="text/html" href="https://indianpedia.org/index.php?title=Kosaraju%27s_algorithm&amp;action=history"/>
	<updated>2026-07-30T04:18:17Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.4</generator>
	<entry>
		<id>https://indianpedia.org/index.php?title=Kosaraju%27s_algorithm&amp;diff=477536&amp;oldid=prev</id>
		<title>CarlNorfleet88 at 09:48, 8 September 2025</title>
		<link rel="alternate" type="text/html" href="https://indianpedia.org/index.php?title=Kosaraju%27s_algorithm&amp;diff=477536&amp;oldid=prev"/>
		<updated>2025-09-08T09:48:15Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Short description|Method of finding a directed graph&amp;#039;s strongly connected components}}&lt;br /&gt;
{{no footnotes|date=July 2020}}&lt;br /&gt;
In [[computer science]], &amp;#039;&amp;#039;&amp;#039;Kosaraju-Sharir&amp;#039;s algorithm&amp;#039;&amp;#039;&amp;#039; (also known as &amp;#039;&amp;#039;&amp;#039;Kosaraju&amp;#039;s algorithm&amp;#039;&amp;#039;&amp;#039;) is a [[linear time]] [[algorithm]] to find the [[strongly connected component]]s of a [[directed graph]].  [[Alfred V. Aho|Aho]], [[John E. Hopcroft|Hopcroft]] and [[Jeffrey D. Ullman|Ullman]] credit it to [[S. Rao Kosaraju]] and [[Micha Sharir]].&amp;lt;ref&amp;gt;{{Cite book |last=Aho |first=Alfred V. |title=Data structures and algorithms |last2=Hopcroft |first2=John E. |last3=Ullman |first3=Jeffrey D. |date=1999 |publisher=Addison-Wesley |isbn=978-0-201-00023-8 |edition=Repr. with corrections |series=Addison-Wesley series in computer science and information processing |location=Reading, Mass.}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{Cite book |last=Cormen |first=Thomas H. |title=Introduction to algorithms |last2=Leiserson |first2=Charles Eric |last3=Rivest |first3=Ronald Linn |last4=Stein |first4=Clifford |date=2009 |publisher=MIT Press |isbn=978-0-262-03384-8 |edition=3rd |location=Cambridge, Massachusetts London, England}}&amp;lt;/ref&amp;gt; Kosaraju suggested it in 1978 but did not publish it, while Sharir independently discovered it and published it in 1981.&amp;lt;ref&amp;gt;{{Cite journal |last=Sharir |first=M. |date=1981 |title=A strong-connectivity algorithm and its applications in data flow analysis |url=https://linkinghub.elsevier.com/retrieve/pii/0898122181900080 |journal=Computers &amp;amp; Mathematics with Applications |language=en |volume=7 |issue=1 |pages=67–72 |doi=10.1016/0898-1221(81)90008-0|url-access=subscription }}&amp;lt;/ref&amp;gt; It makes use of the fact that the [[transpose graph]] (the same graph with the direction of every edge reversed) has exactly the same strongly connected components as the original graph.&lt;br /&gt;
&lt;br /&gt;
==The algorithm==&lt;br /&gt;
The primitive [[graph operations]] that the algorithm uses are to enumerate the vertices of the graph, to store data per vertex (if not in the graph [[data structure]] itself, then in some table that can use vertices as indices), to enumerate the out-neighbours of a vertex (traverse edges in the forward direction), and to enumerate the in-neighbours of a vertex (traverse edges in the backward direction); however the last can be done without, at the price of constructing a representation of the transpose graph during the forward traversal phase. The only additional data structure needed by the algorithm is an ordered list {{math|L}} of graph vertices, that will grow to contain each vertex once.&lt;br /&gt;
&lt;br /&gt;
If strong components are to be represented by appointing a separate root vertex for each component, and assigning to each vertex the root vertex of its component, then Kosaraju&amp;#039;s algorithm can be stated as follows.&lt;br /&gt;
# For each vertex {{mvar|u}} of the graph, mark {{mvar|u}} as unvisited. Let {{math|L}} be empty.&lt;br /&gt;
# For each vertex {{mvar|u}} of the graph do {{code|Visit(u)}}, where {{code|Visit(u)}} is the recursive subroutine:&lt;br /&gt;
#: If {{mvar|u}} is unvisited then:&lt;br /&gt;
#:# Mark {{mvar|u}} as visited.&lt;br /&gt;
#:# For each out-neighbour {{mvar|v}} of {{mvar|u}}, do {{code|Visit(v)}}.&lt;br /&gt;
#:# Prepend {{mvar|u}} to {{math|L}}.&lt;br /&gt;
#: Otherwise do nothing.&lt;br /&gt;
# For each element {{mvar|u}} of {{math|L}} in order, do {{code|Assign(u,u)}} where {{code|Assign(u,root)}} is the recursive subroutine:&lt;br /&gt;
#: If {{mvar|u}} has not been assigned to a component then:&lt;br /&gt;
#:# Assign {{mvar|u}} as belonging to the component whose root is {{mvar|root}}.&lt;br /&gt;
#:# For each in-neighbour {{mvar|v}} of {{mvar|u}}, do {{code|Assign(v,root)}}.&lt;br /&gt;
#: Otherwise do nothing.&lt;br /&gt;
Trivial variations are to instead assign a component number to each vertex, or to construct per-component lists of the vertices that belong to it. The unvisited/visited indication may share storage location with the final assignment of root for a vertex.&lt;br /&gt;
&lt;br /&gt;
The key point of the algorithm is that during the first (forward) traversal of the graph edges, vertices are prepended to the list {{math|L}} in [[Tree_traversal#Post-order|post-order]] relative to the search tree being explored. This means it does not matter whether a vertex {{mvar|v}} was first visited because it appeared in the enumeration of all vertices or because it was the out-neighbour of another vertex {{mvar|u}} that got visited; either way {{mvar|v}} will be prepended to {{math|L}} before {{mvar|u}} is, so if there is a forward path from {{mvar|u}} to {{mvar|v}} then {{mvar|u}} will appear before {{mvar|v}} on the final list {{math|L}} (unless {{mvar|u}} and {{mvar|v}} both belong to the same strong component, in which case their relative order in {{math|L}} is arbitrary). &lt;br /&gt;
&lt;br /&gt;
This means, that each element {{mvar|n}} of the list can be made to correspond to a block {{math|L[&amp;#039;&amp;#039;i&amp;#039;&amp;#039;{{sub|&amp;#039;&amp;#039;n&amp;#039;&amp;#039;-1}}: &amp;#039;&amp;#039;i&amp;#039;&amp;#039;{{sub|&amp;#039;&amp;#039;n&amp;#039;&amp;#039;}}]}}, where the block consists of all the vertices reachable from vertex {{mvar|n}} using just outward edges at each node in the path. It is important to note that no vertex in the block beginning at {{mvar|n}} has an inward link from any of the blocks beginning at some vertex to its right, i.e., the blocks corresponding to vertices {{math|&amp;#039;&amp;#039;i&amp;#039;&amp;#039;{{sub|&amp;#039;&amp;#039;n&amp;#039;&amp;#039;}}, &amp;#039;&amp;#039;i&amp;#039;&amp;#039;{{sub|&amp;#039;&amp;#039;n&amp;#039;&amp;#039;+1}}, … &amp;#039;&amp;#039;N&amp;#039;&amp;#039;}} in the list. This is so, because otherwise the vertex having the inward link (say from the block beginning at {{math|&amp;#039;&amp;#039;n&amp;#039; &amp;#039;&amp;#039; ≥ &amp;#039;&amp;#039;i&amp;#039;&amp;#039;{{sub|&amp;#039;&amp;#039;n&amp;#039;&amp;#039;+1}}}}) would have been already visited and pre-pended to {{math|L}} in the block of {{mvar|n&amp;#039;}}, which is a contradiction. On the other hand, vertices in the block starting at {{mvar|n}} &amp;#039;&amp;#039;&amp;#039;can have&amp;#039;&amp;#039;&amp;#039; edges pointing to the blocks starting at some vertex in {{math|{&amp;#039;&amp;#039;i&amp;#039;&amp;#039;{{sub|&amp;#039;&amp;#039;n&amp;#039;&amp;#039;}}, &amp;#039;&amp;#039;i&amp;#039;&amp;#039;{{sub|&amp;#039;&amp;#039;n&amp;#039;&amp;#039;+1}}, … &amp;#039;&amp;#039;N&amp;#039;&amp;#039;}.}}&lt;br /&gt;
&lt;br /&gt;
Step 3 of the algorithm, starts from {{math|L[0]}}, assigns all vertices which point to it, the same component as {{math|L[0]}}. Note that these vertices can only lie in the block beginning at {{math|L[0]}} as higher blocks can&amp;#039;t have links pointing to vertices in the block of {{math|L[0]}}. Let the set of all vertices that point to {{math|L[0]}} be {{math|In(L[0])}}. Subsequently, all the vertices pointing to these vertices, {{math|In(In(L[0]))}} are added too, and so on till no more vertices can be added. &lt;br /&gt;
&lt;br /&gt;
There is a path to {{math|L[0]}}, from all the vertices added to the component containing {{math|L[0]}}. And there is a path to all the vertices added from {{math|L[0]}}, as all those lie in the block beginning at {{math|L[0]}} (which contains all the vertices reachable from {{math|L[0]}} following outward edges at each step of path). Hence all these form a single strongly connected component. Moreover, no vertex remains, because, to be in this strongly connected component a vertex must be reachable from {{math|L[0]}} and must be able to reach {{math|L[0]}}. All vertices that are able to reach {{math|L[0]}}, if any, lie in the first block only, and all the vertices in first block are reachable from {{math|L[0]}}. So the algorithm chooses all the vertices in the connected component of {{math|L[0]}}. &lt;br /&gt;
&lt;br /&gt;
When we reach vertex {{math|1=v = L[&amp;#039;&amp;#039;i&amp;#039;&amp;#039;]}}, in the loop of step 3, and {{mvar|v}} hasn&amp;#039;t been assigned to any component, we can be sure that all the vertices to the left have made their connected components; that {{mvar|v}} doesn&amp;#039;t belong to any of those components; that {{mvar|v}} doesn&amp;#039;t point to any of the vertices to the left of it. Also, since, no edge from higher blocks to {{mvar|v}}&amp;#039;s block exists, the proof remains same. &lt;br /&gt;
&lt;br /&gt;
As given above, the algorithm for simplicity employs [[depth-first search]], but it could just as well use [[breadth-first search]] as long as the post-order property is preserved.&lt;br /&gt;
&lt;br /&gt;
The algorithm can be understood as identifying the strong component of a vertex {{mvar|u}} as the set of vertices which are reachable from {{mvar|u}} both by backwards and forwards traversal. Writing {{math|&amp;#039;&amp;#039;F&amp;#039;&amp;#039;(&amp;#039;&amp;#039;u&amp;#039;&amp;#039;)}} for the set of vertices reachable from {{mvar|u}} by forward traversal, {{math|&amp;#039;&amp;#039;B&amp;#039;&amp;#039;(&amp;#039;&amp;#039;u&amp;#039;&amp;#039;)}} for the set of vertices reachable from {{mvar|u}} by backwards traversal, and {{math|&amp;#039;&amp;#039;P&amp;#039;&amp;#039;(&amp;#039;&amp;#039;u&amp;#039;&amp;#039;)}} for the set of vertices which appear strictly before {{mvar|u}} on the list {{mvar|L}} after phase 2 of the algorithm, the strong component containing a vertex {{mvar|u}} appointed as root is&lt;br /&gt;
: &amp;lt;math&amp;gt; B(u) \cap F(u) = B(u) \setminus (B(u) \setminus F(u)) = B(u) \setminus P(u).&amp;lt;/math&amp;gt;&lt;br /&gt;
Set intersection is computationally costly, but it is logically equivalent to a double [[set difference]], and since {{tmath|B(u) \setminus F(u) \subseteq P(u)}} it becomes sufficient to test whether a newly encountered element of {{math|&amp;#039;&amp;#039;B&amp;#039;&amp;#039;(&amp;#039;&amp;#039;u&amp;#039;&amp;#039;)}} has already been assigned to a component or not.&lt;br /&gt;
&lt;br /&gt;
== Complexity ==&lt;br /&gt;
Provided the graph is described using an [[adjacency list]], Kosaraju&amp;#039;s algorithm performs two complete traversals of the graph and so runs in Θ(V+E) (linear) time, which is [[asymptotically optimal]] because there is a matching lower bound (any algorithm must examine all vertices and edges). It is the conceptually simplest efficient algorithm, but is not as efficient in practice as [[Tarjan&amp;#039;s strongly connected components algorithm]] and the [[path-based strong component algorithm]], which perform only one traversal of the graph.&lt;br /&gt;
&lt;br /&gt;
If the graph is represented as an [[adjacency matrix]], the algorithm requires &amp;#039;&amp;#039;Ο(V&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;#039;&amp;#039; time.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
*[http://scienceblogs.com/goodmath/2007/10/30/computing-strongly-connected-c/ Good Math, Bad Math: Computing Strongly Connected Components]&lt;br /&gt;
&lt;br /&gt;
[[Category:Graph algorithms]]&lt;br /&gt;
[[Category:Graph connectivity]]&lt;/div&gt;</summary>
		<author><name>CarlNorfleet88</name></author>
	</entry>
</feed>