Kosaraju: Difference between revisions

39,315 bytes added ,  23 days ago
m
(→‎{{header|Perl 6}}: Add a Perl 6 example)
 
(44 intermediate revisions by 15 users not shown)
Line 1:
{{draft task}}
{{wikipedia|Graph}}
[[Category:Algorithm]]
<br>
Kosaraju's algorithm (also known as the Kosaraju–Sharir algorithm) is a linear time algorithm to find the strongly connected components of a directed graph. Aho, Hopcroft and Ullman credit it to an unpublished paper from 1978 by S. Rao Kosaraju. The same algorithm was independently discovered by Micha Sharir and published by him in 1981. 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.
<br>
For this task consider the directed graph with these connections:
0 -> 1
1 -> 2
2 -> 0
3 -> 1, 3 -> 2, 3 -> 4
4 -> 3, 4 -> 5
5 -> 2, 5 -> 6
6 -> 5
7 -> 4, 7 -> 6, 7 -> 7
 
And report the kosaraju strongly connected component for each node.
<br>
;References:
* The article on [[wp:Kosaraju's_algorithm|Wikipedia]].
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F kosaraju(g)
V size = g.len
V vis = [0B] * size
V l = [0] * size
V x = size
V t = [[Int]()] * size
 
F visit(Int u) -> Void
I !@vis[u]
@vis[u] = 1B
L(v) @g[u]
@visit(v)
@t[v] [+]= u
@x--
@l[@x] = u
 
L(u) 0 .< g.len
visit(u)
V c = [0] * size
 
F assign(Int u, root) -> Void
I @vis[u]
@vis[u] = 0B
@c[u] = root
L(v) @t[u]
@assign(v, root)
 
L(u) l
assign(u, u)
R c
 
V g = [[1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7]]
print(kosaraju(g))</syntaxhighlight>
 
{{out}}
<pre>
[0, 0, 0, 3, 3, 5, 5, 7]
</pre>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
 
Line 80 ⟶ 134:
Assign(u, u);
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
{{trans|D}}
<syntaxhighlight lang="cpp">#include <functional>
#include <iostream>
#include <ostream>
#include <vector>
 
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
auto it = v.cbegin();
auto end = v.cend();
 
os << "[";
if (it != end) {
os << *it;
it = std::next(it);
}
while (it != end) {
os << ", " << *it;
it = std::next(it);
}
return os << "]";
}
 
std::vector<int> kosaraju(std::vector<std::vector<int>>& g) {
// 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
auto size = g.size();
std::vector<bool> vis(size); // all false by default
std::vector<int> l(size); // all zero by default
auto x = size; // index for filling l in reverse order
std::vector<std::vector<int>> t(size); // transpose graph
 
// Recursive subroutine 'visit':
std::function<void(int)> visit;
visit = [&](int u) {
if (!vis[u]) {
vis[u] = true;
for (auto v : g[u]) {
visit(v);
t[v].push_back(u); // construct transpose
}
l[--x] = u;
}
};
 
// 2. For each vertex u of the graph do visit(u)
for (int i = 0; i < g.size(); ++i) {
visit(i);
}
std::vector<int> c(size); // used for component assignment
 
// Recursive subroutine 'assign':
std::function<void(int, int)> assign;
assign = [&](int u, int root) {
if (vis[u]) { // repurpose vis to mean 'unassigned'
vis[u] = false;
c[u] = root;
for (auto v : t[u]) {
assign(v, root);
}
}
};
 
// 3: For each element u of l in order, do assign(u, u)
for (auto u : l) {
assign(u, u);
}
 
return c;
}
 
std::vector<std::vector<int>> g = {
{1},
{2},
{0},
{1, 2, 4},
{3, 5},
{2, 6},
{5},
{4, 6, 7},
};
 
int main() {
using namespace std;
 
cout << kosaraju(g) << endl;
 
return 0;
}</syntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|D}}==
{{trans|Kotlin}} (mostly) with output like {{trans|Go}}
<langsyntaxhighlight Dlang="d">import std.container.array;
import std.stdio;
 
Line 150 ⟶ 296:
void main() {
writeln(kosaraju(g));
}</langsyntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program KosarajuApp;
 
uses
System.SysUtils;
 
type
TKosaraju = TArray<TArray<Integer>>;
 
var
g: TKosaraju;
 
procedure Init();
begin
SetLength(g, 8);
g[0] := [1];
g[1] := [2];
g[2] := [0];
g[3] := [1, 2, 4];
g[4] := [3, 5];
g[5] := [2, 6];
g[6] := [5];
g[7] := [4, 6, 7];
end;
 
procedure Println(vector: TArray<Integer>);
var
i: Integer;
begin
write('[');
if (Length(vector) > 0) then
for i := 0 to High(vector) do
begin
write(vector[i]);
if (i < high(vector)) then
write(', ');
end;
 
writeln(']');
end;
 
function Kosaraju(g: TKosaraju): TArray<Integer>;
var
vis: TArray<Boolean>;
L, c: TArray<Integer>;
x: Integer;
t: TArray<TArray<Integer>>;
Visit: TProc<Integer>;
u: Integer;
Assign: TProc<Integer, Integer>;
begin
// 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
SetLength(vis, Length(g));
SetLength(L, Length(g));
x := Length(L);
// index for filling L in reverse order
SetLength(t, Length(g)); // transpose graph
 
// 2. recursive subroutine:
 
Visit := procedure(u: Integer)
begin
if (not vis[u]) then
begin
vis[u] := true;
for var v in g[u] do
begin
Visit(v);
t[v] := concat(t[v], [u]);
// construct transpose
end;
 
dec(x);
L[x] := u;
end;
end;
 
// 2. For each vertex u of the graph do Visit(u)
 
for u := 0 to High(g) do
begin
Visit(u);
end;
 
SetLength(c, Length(g)); // result, the component assignment
 
// 3: recursive subroutine:
 
Assign := procedure(u, root: Integer)
begin
if vis[u] then
// repurpose vis to mean "unassigned"
begin
vis[u] := false;
c[u] := root;
 
for var v in t[u] do
Assign(v, root);
end;
end;
 
// 3: For each element u of L in order, do Assign(u,u)
 
for u in L do
Assign(u, u);
 
Result := c;
end;
 
begin
Init;
Println(Kosaraju(g));
end.</syntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 214 ⟶ 478:
}
return c
}</langsyntaxhighlight>
{{out}}
<pre>
[0 0 0 3 3 5 5 7]
</pre>
 
=={{header|J}}==
 
Implementation:
<syntaxhighlight lang="j">kosaraju=: {{
coerase([cocurrent)cocreate''
visit=: {{
if.y{unvisited do.
unvisited=: 0 y} unvisited
visit y{::out
L=: y,L
end.
}}"0
assign=: {{
if._1=y{assigned do.
assigned=: x y} assigned
x&assign y{::in
end.
}}"0
out=: y
in=: <@I.|:y e.S:0~i.#y
unvisited=: 1#~#y
assigned=: _1#~#y
L=: i.0
visit"0 i.#y
assign~L
assigned
}}</syntaxhighlight>
 
Task example (tree representation: each value here is the index of the parent node):
 
<syntaxhighlight lang="j"> kosaraju 1;2;0;1 2 4;3 5;2 6;5;4 6 7
0 0 0 3 3 5 5 7</syntaxhighlight>
 
Alternatively, we could represent the result as a graph of the same type as our argument graph. The implementation of <tt>visit</tt> remains the same:
 
<syntaxhighlight lang="j">kosarajud=: {{
coerase([cocurrent)cocreate''
visit=: {{
if.y{unvisited do.
unvisited=: 0 y} unvisited
visit y{::out
L=: y,L
end.
}}"0
assign=: {{
if.-.y e.;assigned do.
assigned=: (y,L:0~x{assigned) x} assigned
x&assign y{::in
end.
}}"0
out=: y
in=: <@I.|:y e.S:0~i.#y
unvisited=: 1#~#y
assigned=: a:#~#y
L=: i.0
visit"0 i.#y
assign~L
assigned
}}
 
kosarajud 1;2;0;1 2 4;3 5;2 6;5;4 6 7
┌─────┬┬┬───┬┬───┬┬─┐
│0 2 1│││3 4││5 6││7│
└─────┴┴┴───┴┴───┴┴─┘
</syntaxhighlight>
 
But it would probably be simpler to convert the result from the tree representation to our directed graph representation:
 
<syntaxhighlight lang="j"> ((<@I.@e."1 0)i.@#) 0 0 0 3 3 5 5 7
┌─────┬┬┬───┬┬───┬┬─┐
│0 1 2│││3 4││5 6││7│
└─────┴┴┴───┴┴───┴┴─┘</syntaxhighlight>
 
=={{header|Java}}==
{{trans|Kotlin}}
Output is like Go instead of what Kotlin outputs.
<syntaxhighlight lang="java">import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.IntConsumer;
import java.util.stream.Collectors;
 
public class Kosaraju {
static class Recursive<I> {
I func;
}
 
private static List<Integer> kosaraju(List<List<Integer>> g) {
// 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
int size = g.size();
boolean[] vis = new boolean[size];
int[] l = new int[size];
AtomicInteger x = new AtomicInteger(size);
 
List<List<Integer>> t = new ArrayList<>();
for (int i = 0; i < size; ++i) {
t.add(new ArrayList<>());
}
 
Recursive<IntConsumer> visit = new Recursive<>();
visit.func = (int u) -> {
if (!vis[u]) {
vis[u] = true;
for (Integer v : g.get(u)) {
visit.func.accept(v);
t.get(v).add(u);
}
int xval = x.decrementAndGet();
l[xval] = u;
}
};
 
// 2. For each vertex u of the graph do visit(u)
for (int i = 0; i < size; ++i) {
visit.func.accept(i);
}
int[] c = new int[size];
 
Recursive<BiConsumer<Integer, Integer>> assign = new Recursive<>();
assign.func = (Integer u, Integer root) -> {
if (vis[u]) { // repurpose vis to mean 'unassigned'
vis[u] = false;
c[u] = root;
for (Integer v : t.get(u)) {
assign.func.accept(v, root);
}
}
};
 
// 3: For each element u of l in order, do assign(u, u)
for (int u : l) {
assign.func.accept(u, u);
}
 
return Arrays.stream(c).boxed().collect(Collectors.toList());
}
 
public static void main(String[] args) {
List<List<Integer>> g = new ArrayList<>();
for (int i = 0; i < 8; ++i) {
g.add(new ArrayList<>());
}
g.get(0).add(1);
g.get(1).add(2);
g.get(2).add(0);
g.get(3).add(1);
g.get(3).add(2);
g.get(3).add(4);
g.get(4).add(3);
g.get(4).add(5);
g.get(5).add(2);
g.get(5).add(6);
g.get(6).add(5);
g.get(7).add(4);
g.get(7).add(6);
g.get(7).add(7);
 
List<Integer> output = kosaraju(g);
System.out.println(output);
}
}</syntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|jq}}==
{{trans|Go}}
<syntaxhighlight lang="jq">
# Fill an array of the specified length with the input value
def dimension($n): . as $in | [range(0;$n) | $in];
 
# $graph should be an adjacency-list graph with IO==0
def korasaju($graph):
($graph|length) as $length
| def init: {
vis: (false | dimension($length)), # visited
L: [], # for an array of $length integers
t: ([]|dimension($length)), # transposed graph
x: $length # index
};
 
# input: {vis, L, t, x, t}
def visit($u):
if .vis[$u] | not
then .vis[$u] = true
| reduce ($graph[$u][]) as $v (.;
visit($v)
| .t[$v] += [$u] )
| .x -= 1
| .L[.x] = $u
else .
end ;
 
# input: {vis, t, c}
def assign($u; $root):
if .vis[$u]
then .vis[$u] = false
| .c[$u] = $root
| reduce .t[$u][] as $v (.; assign($v; $root))
else .
end ;
 
# For each vertex u of the graph, mark u as unvisited.
init
 
# For each vertex u of the graph do visit(u)
| reduce range(0;$length) as $u (.; visit($u))
| .c = (null|dimension($length))
 
# For each element u of L in order, do assign(u, u)
| reduce .L[] as $u (.; assign($u; $u) )
| .c ;
 
# An example adjacency list using IO==1
def g: [
[1],
[2],
[0],
[1, 2, 4],
[3, 5],
[2, 6],
[5],
[4, 6, 7]
];
 
korasaju(g)</syntaxhighlight>
{{out}}
With the jq program above in korasaju.jq, the invocation `jq -nc -f korasaju.jq` produces:
<syntaxhighlight lang="sh">
[0,0,0,3,3,5,5,7]
</syntaxhighlight>
 
=={{header|Julia}}==
Line 224 ⟶ 721:
{{trans|Go}}
 
<langsyntaxhighlight lang="julia">function korasaju(g::Vector{Vector{T}}) where T<:Integer
# 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
vis = falses(length(g))
Line 266 ⟶ 763:
 
g = [[2], [3], [1], [2, 3, 5], [4, 6], [3, 7], [6], [5, 7, 8]]
println(korasaju(g))</langsyntaxhighlight>
 
{{out}}
<pre>[1, 1, 1, 4, 4, 6, 6, 8]</pre>
 
=={{header|K}}==
{{works with|ngn/k}}
<syntaxhighlight lang=K>F:{[g] / graph
n: #g / number of vertices
v::&n / visited?
L::!0 / dfs order
V: {[g;x] $[v x;;[v[x]:1;o[g]'g x;L::x,L]];}[g]
V'!n / Visit
G: @[n#,!0;g;,;!n] / transposed graph
c::n#-1 / assigned components
A: {[G;x;y] $[-1=c x;[c[x]:y;G[x]o[G]'y];]}[G]'
A'/2#,L / Assign
.=c}</syntaxhighlight>
<syntaxhighlight lang=K> F(1;2;0;1 2 4;3 5;2 6;5;4 6 7)
(0 1 2
3 4
5 6
,7)</syntaxhighlight>
 
Alternative implementation, without global assignments:
 
<syntaxhighlight lang=K>F:{[g] /graph
n:#g /number of vertices
G:@[n#,!0;g;,;!n] /transposed graph
V:{[g;L;x]$[^L?x;(1_(x,L)o[g]/g x),x;L]}[g]
L:|V/[!0;!#g] /Visit
A:{[G;c;u;r]$[0>c u;o[G]/[@[c;u;:;r];G u;r];c]}[G]
.=A/[n#-1;L;L]} /Assign</syntaxhighlight>
 
(result is the same)
 
{{works with|Kona}}<syntaxhighlight lang=K>F:{[g] / graph
n: #g / number of vertices
v::&n / visited?
L::!0 / dfs order
V: {[g;x] :[v x;;[v[x]:1;_f[g]'g x;L::x,L]];}[g]
V'!n / Visit
G: @[n#,!0;g;,;!n] / transposed graph
c::n#-1 / assigned components
A: {[G;x;y] :[-1=c x;[c[x]:y;G[x]_f[G]'y];]}[G]'
A'/2#,L / Assign
.=c}</syntaxhighlight>
 
(result is the same)
 
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">// version 1.1.3
 
/* the list index is the first vertex in the edge(s) */
Line 331 ⟶ 873:
fun main(args: Array<String>) {
println(kosaraju(g).joinToString("\n"))
}</langsyntaxhighlight>
 
{{out}}
Line 341 ⟶ 883:
</pre>
 
=={{header|Perl 6Lua}}==
{{trans|C++}}
{{works with|Rakudo|2018.09}}
<syntaxhighlight lang="lua">function write_array(a)
{{trans|Python}}{{trans|Kotlin}}
io.write("[")
for i=0,#a do
if i>0 then
io.write(", ")
end
io.write(tostring(a[i]))
end
io.write("]")
end
 
<lang perl6>subfunction kosaraju (*@g) {
-- 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
my %visited;
mylocal @stack;size = #g
my @transpose;
my @connected;
 
sublocal visitvis ($u)= {}
for i=0,size do
unless %visited{$u} {
-- all false by %visited{$u} = True;default
for |@gvis[$ui] -> $v= {false
end
 
local l = {}
for i=0,size do
-- all zero by default
l[i] = 0
end
 
local x = size+1 -- index for filling l in reverse order
 
local t = {} -- transpose graph
 
-- Recursive subroutine 'visit'
function visit(u)
if not vis[u] then
vis[u] = true
for i=0,#g[u] do
local v = g[u][i]
visit(v)
if t[v] then
local a = t[v]
a[#a+1] = u
else
t[v] = {[0]=u}
end
end
x = x - 1
l[x] = u
end
end
 
-- 2. For each vertex u of the graph do visit(u)
for i=0,#g do
visit(i)
end
local c = {}
for i=0,size do
-- used for component assignment
c[i] = 0
end
 
-- Recursive subroutine 'assign'
function assign(u, root)
if vis[u] then -- repurpose vis to mean 'unassigned'
vis[u] = false
c[u] = root
for i=0,#t[u] do
local v = t[u][i]
assign(v, root)
end
end
end
 
-- 3: For each element u of l in order, do assign(u, u)
for i=0,#l do
local u = l[i]
assign(u, u)
end
 
return c
end
 
-- main
local g = {
[0]={[0]=1},
[1]={[0]=2},
[2]={[0]=0},
[3]={[0]=1, [1]=2, [2]=4},
[4]={[0]=3, [1]=5},
[5]={[0]=2, [1]=6},
[6]={[0]=5},
[7]={[0]=4, [1]=6, [2]=7},
}
 
write_array(kosaraju(g))
print()</syntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">g = Graph[{0 -> 1, 1 -> 2, 2 -> 0, 3 -> 1, 3 -> 2, 3 -> 4, 4 -> 3,
4 -> 5, 5 -> 2, 5 -> 6, 6 -> 5, 7 -> 4, 7 -> 6, 7 -> 7}];
cc = ConnectedComponents[g]
Catenate[ConstantArray[Min[#], Length[#]] & /@ SortBy[cc, First]]</syntaxhighlight>
{{out}}
<pre>{{0, 1, 2}, {5, 6}, {3, 4}, {7}}
{0, 0, 0, 3, 3, 5, 5, 7}</pre>
 
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">type
Vertex = int
Graph = seq[seq[Vertex]]
Scc = seq[Vertex]
 
func korasaju(g: Graph): seq[Scc] =
 
var
size = g.len
visited = newSeq[bool](size) # All false by default.
l = newSeq[Vertex](size) # All zero by default.
x = size # Index for filling "l" in reverse order.
t = newSeq[seq[Vertex]](size) # Transposed graph.
c = newSeq[Vertex](size) # Used for component assignment.
 
func visit(u: Vertex) =
if not visited[u]:
visited[u] = true
for v in g[u]:
visit(v)
t[v].add(u) # Construct transposed graph.
dec x
l[x] = u
 
func assign(u, root: Vertex) =
if visited[u]:
# Repurpose visited to mean 'unassigned'.
visited[u] = false
c[u] = root
for v in t[u]: v.assign(root)
 
for u in 0..g.high: u.visit()
for u in l: u.assign(u)
 
# Build list of strongly connected components.
var prev = -1
for v1, v2 in c:
if v2 != prev:
prev = v2
result.add @[]
result[^1].add v1
 
 
when isMainModule:
let g = @[@[1], @[2], @[0], @[1, 2, 4], @[3, 5], @[2, 6], @[5], @[4, 6, 7]]
for scc in korasaju(g): echo $scc</syntaxhighlight>
 
{{out}}
<pre>@[0, 1, 2]
@[3, 4]
@[5, 6]
@[7]</pre>
 
=={{header|Pascal}}==
Works with FPC (tested with version 3.2.2).
<syntaxhighlight lang="pascal">
program Kosaraju_SCC;
{$mode objfpc}{$modeswitch arrayoperators}
{$j-}{$coperators on}
type
TDigraph = array of array of Integer;
 
procedure PrintComponents(const g: TDigraph);
var
Visited: array of Boolean = nil;
RevPostOrder: array of Integer = nil;
gr: TDigraph = nil; //reversed graph
Counter, Next: Integer;
FirstItem: Boolean;
 
procedure Dfs1(aNode: Integer);
begin
Visited[aNode] := True;
for Next in g[aNode] do begin
gr[Next] += [aNode];
if not Visited[Next] then
Dfs1(Next);
end;
RevPostOrder[Counter] := aNode;
Dec(Counter);
end;
 
procedure Dfs2(aNode: Integer);
begin
Visited[aNode] := True;
for Next in gr[aNode] do
if not Visited[Next] then
Dfs2(Next);
if FirstItem then begin
FirstItem := False;
Write(aNode);
end else
Write(', ', aNode);
end;
 
var
Node: Integer;
begin
SetLength(Visited, Length(g));
SetLength(RevPostOrder, Length(g));
SetLength(gr, Length(g));
Counter := High(g);
for Node := 0 to High(g) do
if not Visited[Node] then
Dfs1(Node);
FillChar(Pointer(Visited)^, Length(Visited), 0);
for Node in RevPostOrder do
if not Visited[Node] then begin
FirstItem := True;
Write('[');
Dfs2(Node);
WriteLn(']');
end;
end;
 
const
g: TDigraph = (
(1),
(2),
(0),
(1, 2, 4),
(3, 5),
(2, 6),
(5),
(4, 6, 7)
);
begin
PrintComponents(g);
end.
</syntaxhighlight>
{{out}}
<pre>
[7]
[4, 3]
[6, 5]
[1, 2, 0]
</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
 
sub kosaraju {
our(%k) = @_;
our %g = ();
our %h;
my $i = 0;
$g{$_} = $i++ for sort keys %k;
$h{$g{$_}} = $_ for keys %g; # invert
 
our(%visited, @stack, @transpose, @connected);
sub visit {
my($u) = @_;
unless ($visited{$u}) {
$visited{$u} = 1;
for my $v (@{$k{$u}}) {
visit($v);
push @{$transpose[$g{$v}].push:}, $u;
}
push @stack.unshift:, $u;
}
}
 
sub assign ($u, $root) {
if %visited{my($u}, $root) = {@_;
if %($visited{$u}) = False;{
@connected[$visited{$u]} = $root0;
assign($_, $root) for |@transposeconnected[$g{$u}] = $root;
assign($_, $root) for @{$transpose[$g{$u}]};
}
}
 
.&visit($_) for ^@sort keys %g;
assign($_, $_) for reverse @stack;
 
@connectedmy %groups;
for my $i (0..$#connected) {
my $id = $g{$connected[$i]};
push @{$groups{$id}}, $h{$i};
}
say join ' ', @{$groups{$_}} for sort keys %groups;
}
 
my %test1 = (
my @verticies = (1),(2),(0),(1,2,4),(3,5),(2,6),(5),(4,6,7);
0 => [1],
my @connected = kosaraju @verticies;
1 => [2],
my %scc;
2 => [0],
@connected.antipairs.map: { %scc{$_.key}.push: $_.value }
3 => [1, 2, 4],
4 => [3, 5],
5 => [2, 6],
6 => [5],
7 => [4, 6, 7]
);
 
my %test2 = (
say ' Connected graph: ', @connected;
'Andy' => ['Bart'],
say 'Strongly connected components: ', |%scc.sort».values».Slip</lang>
'Bart' => ['Carl'],
'Carl' => ['Andy'],
'Dave' => [<Bart Carl Earl>],
'Earl' => [<Dave Fred>],
'Fred' => [<Carl Gary>],
'Gary' => ['Fred'],
'Hank' => [<Earl Gary Hank>]
);
 
kosaraju(%test1);
say '';
kosaraju(%test2);</syntaxhighlight>
{{out}}
<pre>0 1 2
<pre> Connected graph: [0 0 0 3 3 5 5 7]
3 4
Strongly connected components: [0 1 2][3 4][5 6][7]</pre>
5 6
7
 
Andy Bart Carl
Dave Earl
Fred Gary
Hank</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">visited</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">v</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">v</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">u</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">l</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">u</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">assign</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">root</span><span style="color: #0000FF;">=</span><span style="color: #000000;">u</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">root</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">assign</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">][</span><span style="color: #000000;">v</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">root</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">korasaju</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">visited</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">len</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">u</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">assign</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">g</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">}}</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">korasaju</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
{1,1,1,4,4,6,6,8}
</pre>
 
=={{header|Python}}==
Works with Python 2
<lang python>def kosaraju(g):
<syntaxhighlight lang="python">def kosaraju(g):
class nonlocal: pass
 
Line 427 ⟶ 1,307:
 
g = [[1], [2], [0], [1,2,4], [3,5], [2,6], [5], [4,6,7]]
print kosaraju(g)</langsyntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
Syntax requirements have changed. This version works with Python 3.
<syntaxhighlight lang="python3">def kosaraju(g):
size = len(g)
vis = [False] * size
l = [0] * size
x = size
t = [[] for _ in range(size)]
 
def visit(u):
nonlocal x
if not vis[u]:
vis[u] = True
for v in g[u]:
visit(v)
t[v].append(u)
x -= 1
l[x] = u
 
for u in range(size):
visit(u)
c = [0] * size
 
def assign(u, root):
if vis[u]:
vis[u] = False
c[u] = root
for v in t[u]:
assign(v, root)
 
for u in l:
assign(u, u)
 
return c
 
 
g = [[1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7]]
print(kosaraju(g))</syntaxhighlight>
 
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
 
(require racket/dict)
Line 464 ⟶ 1,386:
(3 1 2 4) ; equvalent to (3 . (1 2 4))
(4 5 3)
(7 4 7 6))))</langsyntaxhighlight>
 
{{out}}
 
<pre>'((7) (6 5) (4 3) (2 1 0))</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.09}}
Inspired by Python & Kotlin entries.
 
Accepts a hash of lists/arrays holding the vertex (name => (neighbors)) pairs. No longer limited to continuous, positive, integer vertex names.
 
<syntaxhighlight lang="raku" line>sub kosaraju (%k) {
my %g = %k.keys.sort Z=> flat ^%k;
my %h = %g.invert;
my %visited;
my @stack;
my @transpose;
my @connected;
sub visit ($u) {
unless %visited{$u} {
%visited{$u} = True;
for |%k{$u} -> $v {
visit($v);
@transpose[%g{$v}].push: $u;
}
@stack.push: $u;
}
}
sub assign ($u, $root) {
if %visited{$u} {
%visited{$u} = False;
@connected[%g{$u}] = $root;
assign($_, $root) for |@transpose[%g{$u}];
}
}
.&visit for %g.keys;
assign($_, $_) for @stack.reverse;
 
(|%g{@connected}).pairs.categorize( *.value, :as(*.key) ).values.map: { %h{|$_} };
}
 
# TESTING
 
-> $test { say "\nStrongly connected components: ", |kosaraju($test).sort } for
 
# Same test data as all other entries, converted to a hash of lists
(((1),(2),(0),(1,2,4),(3,5),(2,6),(5),(4,6,7)).pairs.hash),
 
# Same layout test data with named vertices instead of numbered.
(
%(:Andy<Bart>,
:Bart<Carl>,
:Carl<Andy>,
:Dave<Bart Carl Earl>,
:Earl<Dave Fred>,
:Fred<Carl Gary>,
:Gary<Fred>,
:Hank<Earl Gary Hank>)
)</syntaxhighlight>
{{out}}
<pre>
Strongly connected components: (0 1 2)(3 4)(5 6)(7)
 
Strongly connected components: (Andy Bart Carl)(Dave Earl)(Fred Gary)(Hank)</pre>
 
=={{header|Sidef}}==
{{trans|Julia}}
<langsyntaxhighlight lang="ruby">func korasaju(Array g) {
# 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
var vis = g.len.of(false)
Line 518 ⟶ 1,504:
 
var g = [[1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7]]
say korasaju(g)</langsyntaxhighlight>
{{out}}
<pre>
[0, 0, 0, 3, 3, 5, 5, 7]
</pre>
 
=={{header|Standard ML}}==
<syntaxhighlight lang="sml">datatype 'a node = Node of 'a * bool ref * 'a node list ref * 'a node list ref
 
fun node x = Node (x, ref false, ref nil, ref nil)
fun mark (Node (_, r, _, _)) = !r before r := true
fun unmark (Node (_, r, _, _)) = !r before r := false
 
fun value (Node (x, _, _, _)) = x
fun sources (Node (_, _, ref xs, _)) = xs
fun targets (Node (_, _, _, ref ys)) = ys
 
fun connect (m, n) =
let
val Node (_, _, _, ns) = m
val Node (_, _, ms, _) = n
in
ms := m :: !ms;
ns := n :: !ns
end
 
datatype 'a step = One of 'a | Many of 'a list
 
fun visit (ms, nil) = ms
| visit (ms, One m :: ss) = visit (m :: ms, ss)
| visit (ms, Many nil :: ss) = visit (ms, ss)
| visit (ms, Many (n :: ns) :: ss) =
if mark n then
visit (ms, Many ns :: ss)
else
visit (ms, Many (targets n) :: One n :: Many ns :: ss)
 
fun assign (xs, nil) = xs
| assign (xs, nil :: ss) = assign (xs, ss)
| assign (xs, (n :: ns) :: ss) =
if unmark n then
assign (value n :: xs, sources n :: ns :: ss)
else
assign (xs, ns :: ss)
 
fun assigns (xs, nil) = xs
| assigns (xs, n :: ns) =
if unmark n then
let
val x = sources n :: nil
val x = value n :: assign (nil, x)
in
assigns (x :: xs, ns)
end
else
assigns (xs, ns)
 
fun kosaraju xs = assigns (nil, visit (nil, Many xs :: nil))
 
fun make (n, is, ijs) =
let
val xs = Vector.tabulate (n, node)
fun item i = Vector.sub (xs, i)
fun step (i, j) = connect (item i, item j)
fun path (i :: j :: js) = (step (i, j); path (j :: js))
| path _ = ()
in
map item is before app path ijs
end
 
val is = 0 :: nil
val ijs =
[0, 1, 2, 0, 3, 4, 0, 5, 7] ::
[0, 9, 10, 11, 12, 9, 11] ::
[1, 12] ::
[3, 5, 6, 7, 8, 6, 15] ::
[5, 13, 14, 13, 15] ::
[8, 15] ::
[10, 13] ::
nil
 
val ns = make (16, is, ijs)
val xs = kosaraju ns</syntaxhighlight>
{{out}}
<pre>
> xs;
val it = [[15], [13, 14], [9, 10, 11, 12], [6, 7, 8], [5], [0, 1, 2, 3, 4]]: int list list
</pre>
 
=={{header|Swift}}==
 
{{trans|D}}
 
<syntaxhighlight lang="swift">func kosaraju(graph: [[Int]]) -> [Int] {
let size = graph.count
var x = size
var vis = [Bool](repeating: false, count: size)
var l = [Int](repeating: 0, count: size)
var c = [Int](repeating: 0, count: size)
var t = [[Int]](repeating: [], count: size)
 
func visit(_ u: Int) {
guard !vis[u] else {
return
}
 
vis[u] = true
 
for v in graph[u] {
visit(v)
t[v].append(u)
}
 
x -= 1
l[x] = u
}
 
for u in 0..<graph.count {
visit(u)
}
 
func assign(_ u: Int, root: Int) {
guard vis[u] else {
return
}
 
vis[u] = false
c[u] = root
 
for v in t[u] {
assign(v, root: root)
}
}
 
for u in l {
assign(u, root: u)
}
 
return c
}
 
let graph = [
[1],
[2],
[0],
[1, 2, 4],
[3, 5],
[2, 6],
[5],
[4, 6, 7]
]
 
print(kosaraju(graph: graph))</syntaxhighlight>
 
{{out}}
 
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Visual Basic .NET}}==
{{trans|Java}}
<syntaxhighlight lang="vbnet">Module Module1
 
Function Kosaraju(g As List(Of List(Of Integer))) As List(Of Integer)
Dim size = g.Count
Dim vis(size - 1) As Boolean
Dim l(size - 1) As Integer
Dim x = size
 
Dim t As New List(Of List(Of Integer))
For i = 1 To size
t.Add(New List(Of Integer))
Next
 
Dim visit As Action(Of Integer) = Sub(u As Integer)
If Not vis(u) Then
vis(u) = True
For Each v In g(u)
visit(v)
t(v).Add(u)
Next
x -= 1
l(x) = u
End If
End Sub
 
For i = 1 To size
visit(i - 1)
Next
Dim c(size - 1) As Integer
 
Dim assign As Action(Of Integer, Integer) = Sub(u As Integer, root As Integer)
If vis(u) Then
vis(u) = False
c(u) = root
For Each v In t(u)
assign(v, root)
Next
End If
End Sub
 
For Each u In l
assign(u, u)
Next
 
Return c.ToList
End Function
 
Sub Main()
Dim g = New List(Of List(Of Integer)) From {
New List(Of Integer) From {1},
New List(Of Integer) From {2},
New List(Of Integer) From {0},
New List(Of Integer) From {1, 2, 4},
New List(Of Integer) From {3, 5},
New List(Of Integer) From {2, 6},
New List(Of Integer) From {5},
New List(Of Integer) From {4, 6, 7}
}
 
Dim output = Kosaraju(g)
Console.WriteLine("[{0}]", String.Join(", ", output))
End Sub
 
End Module</syntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang="wren">var kosaraju = Fn.new { |g|
var gc = g.count
// 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
var vis = List.filled(gc, false)
var l = List.filled(gc, 0)
var x = gc // index for filling l in reverse order
var t = List.filled(gc, null) // transpose graph
for (i in 0...gc) t[i] = []
var visit // recursive function
visit = Fn.new { |u|
if (!vis[u]) {
vis[u] = true
for (v in g[u]) {
visit.call(v)
t[v].add(u) // construct transpose
}
x = x - 1
l[x] = u
}
}
// 2. For each vertex u of the graph do visit.call(u).
for (i in 0...gc) visit.call(i)
var c = List.filled(gc, 0) // result, the component assignment
var assign // recursive function
assign = Fn.new { |u, root|
if (vis[u]) { // repurpose vis to mean 'unassigned'
vis[u] = false
c[u] = root
for (v in t[u]) assign.call(v, root)
}
}
// 3: For each element u of l in order, do assign.call(u,u).
for (u in l) assign.call(u, u)
return c
}
 
var g = [ [1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7] ]
System.print(kosaraju.call(g))</syntaxhighlight>
 
{{out}}
<pre>
Line 525 ⟶ 1,778:
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">const VISITED=0,ASSIGNED=1;
 
fcn visit(u,G,L){ // u is ((visited,assigned), (id,edges))
Line 565 ⟶ 1,818:
 
return(components);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl"> // graph from https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
// with vertices id zero based (vs 1 based in article)
// ids start at zero and are consecutive (no holes), graph is unsorted
Line 572 ⟶ 1,825:
T( T(0,1), T(2,0), T(5,2,6), T(6,5),
T(1,2), T(3,1,2,4), T(4,5,3), T(7,4,7,6) );
kosaraju(graph);</langsyntaxhighlight>
{{out}}
<pre>
1,480

edits