Task: Kosaraju



C#: using System;
using System.Collections.Generic;

class Node
{
	public enum Colors
	{
		Black, White, Gray
	}

	public Colors color { get; set; }
	public int N { get; }
	
	public Node(int n)
	{
		N = n;
		color = Colors.White;
	}
}

class Graph
{
	public HashSet<Node> V { get; }
	public Dictionary<Node, HashSet<Node>> Adj { get; }

	
	
	
	public void Kosaraju()
	{
		var L = new HashSet<Node>();

		Action<Node> Visit = null;
		Visit = (u) =>
		{
			if (u.color == Node.Colors.White)
			{
				u.color = Node.Colors.Gray;

				foreach (var v in Adj[u])
					Visit(v);

				L.Add(u);
			}
		};

		Action<Node, Node> Assign = null;
		Assign = (u, root) =>
		{
			if (u.color != Node.Colors.Black)
			{
				if (u == root)
					Console.Write("SCC: ");

				Console.Write(u.N + " ");
				u.color = Node.Colors.Black;

				foreach (var v in Adj[u])
					Assign(v, root);

				if (u == root)
					Console.WriteLine();
			}
		};

		foreach (var u in V)
			Visit(u);

		foreach (var u in L)
			Assign(u, u);
	}
}



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) {
        
        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;
            }
        };

        
        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]) {  
                vis[u] = false;
                c[u] = root;
                for (Integer v : t.get(u)) {
                    assign.func.accept(v, root);
                }
            }
        };

        
        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);
    }
}