Cod sursa(job #1746508)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 23 august 2016 14:29:38
Problema Componente tare conexe Scor 0
Compilator java Status done
Runda Arhiva educationala Marime 6.61 kb
import java.io.*;
import java.util.*;

public class Main {

    public static void main(String[] args) throws FileNotFoundException {
        InputReader in = new InputReader(new FileInputStream("ctc.in"));
        PrintWriter out = new PrintWriter(new FileOutputStream("ctc.out"));

        int N = in.nextInt();
        int M = in.nextInt();

        Graph G = new Graph(N);

        for (int i = 0; i < M; i++) {
            int x = in.nextInt();
            int y = in.nextInt();
            G.addEdge(x, y);
        }

        StronglyConnectedComponents SCC = new StronglyConnectedComponents(G);
        int[] color = SCC.computeSCCs();

        ArrayList<ArrayList<Integer>> lists = new ArrayList<>(N);

        for (int i = 0; i < N; i++) {
            lists.add(new ArrayList<Integer>());
        }

        for (int i = 0; i < N; i++) {
            lists.get(color[i]).add(i + 1);
        }

        int numberSCCs = 0;

        for (int i = 0; i < N; i++) {
            if (!lists.get(i).isEmpty())
                numberSCCs++;
        }

        out.println(numberSCCs);

        for (int i = 0; i < N; i++) {
            if (!lists.get(i).isEmpty()){
                for (int x : lists.get(i)) {
                    out.printf("%d ", x);
                }
                out.println();
            }
        }

        in.close();
        out.close();
    }

    static class InputReader{
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 65536);
            tokenizer = null;
        }

        private String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()){
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                }
                catch (IOException e){
                    throw new RuntimeException(e);
                }
            }

            return  tokenizer.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(nextToken());
        }

        String nextString(){
            return nextToken();
        }
    }


    static class Graph{
        private static class Edge{
            int node;
            int next;

            Edge(int node, int next){
                this.node = node;
                this.next = next;
            }
        }

        final static int NIL = -1;
        private int[] head;
        private int[] degree;
        private ArrayList<Edge> graph;

        private int N;
        private int counter;

        Graph(int N){
            initialize(N);
        }

        public int getN() {
            return N;
        }

        private void initialize(final int N){
            head = new int[N];
            degree = new int[N];
            graph = new ArrayList<>();

            this.N = N;
            this.counter = 0;

            Arrays.fill(head, NIL);
            Arrays.fill(degree, 0);
        }

        void addEdge(int x, int y){
            if (!(1 <= x && x <= N)) throw new AssertionError();
            x--; y--;
            graph.add(new Edge(y, head[x]));
            head[x] = counter++;
            degree[x]++;
        }

        int getHead(int node){
            if (!(1 <= node && node <= N)) throw new AssertionError();
            node--;
            return head[node];
        }

        int getNext(int p){
            if (!(0 <= p && p < counter)) throw new AssertionError();
            return graph.get(p).next;
        }

        int getNeighbour(int p){
            if (!(0 <= p && p < counter)) throw new AssertionError();
            return graph.get(p).node + 1;
        }

        boolean isEmpty(int node){
            if (!(1 <= node && node <= N)) throw new AssertionError();
            node--;
            return head[node] == NIL;
        }

        int size(int node){
            assert 1 <= node && node <= N;
            node--;
            return degree[node];
        }

        Graph transpose(){
            Graph GT = new Graph(N);

            for (int i = 1; i <= N; i++) {
                for (int son : getNeighours(i))
                    GT.addEdge(son, i);
            }

            return GT;
        }

        List<Integer> getNeighours(int node){
            if (!(1 <= node && node <= N)) throw new AssertionError();

            List<Integer> list = new ArrayList<Integer>();

            for (int p = head[node - 1]; p != NIL; p = graph.get(p).next) {
                list.add(graph.get(p).node + 1);
            }

            return list;
        }
    }

    static class StronglyConnectedComponents {
        private Graph G;
        private Graph GT;
        private int N;

        StronglyConnectedComponents(Graph graph){
            G = graph;
            GT = graph.transpose();
            N = graph.getN();
        }

        private void dfs(int node, boolean[] visited, List<Integer> list){
            visited[node] = true;

            for (int son : G.getNeighours(node + 1)){
                if (!visited[son - 1])
                    dfs(son - 1, visited, list);
            }

            list.add(node);
        }

        private void dfsT(int node, boolean[] visited, int[] color, int currentColor){
            color[node] = currentColor;
            visited[node] = false;

            for (int son : GT.getNeighours(node + 1)){
                if (visited[son - 1])
                    dfsT(son - 1, visited, color, currentColor);
            }
        }

        int[] topologicalSorting(){
            boolean[] visited = new boolean[N];
            Arrays.fill(visited, false);

            List<Integer> list = new ArrayList<Integer>();

            for (int i = 0; i < N; i++) {
                if (!visited[i])
                    dfs(i, visited, list);
            }

            int[] array = new int[list.size()];

            for (int i = 0; i < N; i++) {
                array[i] = list.get(i);
            }

            return array;
        }

        int[] computeSCCs(){
            boolean[] visited = new boolean[N];
            Arrays.fill(visited, false);

            int[] color = new int[N];
            Arrays.fill(color, -1);

            ArrayList<Integer> list = new ArrayList<Integer>();

            for (int i = 0; i < N; i++) {
                if (!visited[i])
                    dfs(i, visited, list);
            }

            int numberOfSCCs = 0;

            for (int i = N - 1; i >= 0; i--) {
                int v = list.get(i);

                if (visited[v]){
                    dfsT(v, visited, color, numberOfSCCs++);
                }
            }

            return color;
        }
    }
}