Реализация алгоритма Косараю - PullRequest
0 голосов
/ 15 апреля 2020
import java.util.*;
import java.io.*;
public class scc1 {
    static int N = 875714;
    static boolean[] visited = new boolean[N];
    public static void main(String[] args) throws IOException{
        Arrays.fill(visited, false);
        BufferedReader in = new BufferedReader(new FileReader("scc1.txt"));
        ArrayList<LinkedList<Integer>> graph = new ArrayList<LinkedList<Integer>>();
        for(int i=0;i<N;i++)
            graph.add(new LinkedList<Integer>());
        String[] adjacents = new String[2];
        String line;
        while((line = in.readLine()) != null){
            adjacents = line.split(" ");
            graph.get(Integer.parseInt(adjacents[0])-1).add(0,Integer.parseInt(adjacents[1]));
            graph.get(Integer.parseInt(adjacents[1])-1).add(0,-Integer.parseInt(adjacents[0]));
        }
        in.close();
        System.out.println(scc(graph));
    }
    static List<Integer> scc(ArrayList<LinkedList<Integer>> graph){
        List<Integer> res = new LinkedList<>(); // to store the 5 largest SCCs
        int s,t;
        Stack<Integer> fTime = new Stack<>(); // stores the finishing time during the 1st pass
        Stack<Integer> stack = new Stack<Integer>(); // used for DFS implementation
        for(int i=N;i>0;i--){             // 1st pass
            if(!visited[i-1])
                dfsUtil(graph, stack,fTime, i,-1);
        }
        Arrays.fill(visited, false);
        Stack<Integer> size = new Stack<>(); // stores the size of the current SSC
        while(!fTime.isEmpty()){
            size.add(1);
            t = fTime.pop();
            if(!visited[t-1]){
                dfsUtil(graph, stack, size, t, 1);
                if(res.size()<5){
                    res.add(size.pop());
                }
                else{
                    Collections.sort(res);
                    if((s = size.pop()) > res.get(0))
                        res.set(0, s);
                }
            }
        }
        return res;
    }
    static void dfsUtil(ArrayList<LinkedList<Integer>> graph, Stack<Integer> stack,Stack<Integer> fill, int u,int order){
        visited[u-1] = true;
        int size = 0;
        if(order == 1)
            size = fTime.pop();
        ListIterator<Integer> itr = graph.get(u-1).listIterator();
        int temp = 0, flag = 0;
        while(itr.hasNext()){
            temp = itr.next()*order;
            if(temp > 0){
                if(!visited[temp-1]){
                    if(order == 1){
                        size++;
                        fTime.add(size);
                    }
                    stack.push(u);
                    flag = 1;
                    break;
                }
            }
        }
        if(flag == 1){
            dfsUtil(graph, stack, fill, temp, order);
        }       
        else{
            if(order < 0)
                fTime.add(u);
            if(stack.isEmpty()){
                if(order == 1)
                    fTime.add(size);
                return;
            }
            else{
                if(order == 1)
                    fTime.add(size);
                dfsUtil(graph, stack, fill, stack.pop(), order);
            }
        }
    }
}

Это программа для расчета размеров 5 самых больших сильно связанных компонентов графа. Я должен запустить график с 875 714 вершинами. Я пробовал небольшие тестовые случаи, чтобы знать, что это логически правильно. Но из-за такого большого размера я получаю ошибку переполнения стека. Ниже приведена ссылка на входной файл.

https://github.com/SSQ/Coursera-Stanford-Graph-Search-Shortest-Paths-and-Data-Structures/blob/master/Programming%20Assignment%201/SCC.zip

Параметр «Порядок» используется для указания порядка обхода. Параметр fill - это стек, который должен быть заполнен. для первого прохода это «время», а для второго прохода это «размер». Я пробовал запустить только первый проход. Даже тогда я в конечном итоге с той же ошибкой. Я потерялся здесь, пожалуйста, помогите мне.

...