Share another solution based on ‎Kosaraju's algorithm which is eaier to understand
For strongly connected component in directed graph, it will still be strongly connected in the reverse graph.\nFirst do dfs on the graph and then do a dfs in th
For strongly connected component in directed graph, it will still be strongly connected in the reverse graph.\nFirst do dfs on the graph and then do a dfs in the reverse graph, if an element can be reached from one point, then these points are strongly connected.\nOne issue in this problem is that the given graph is undirected.\nThe way to solve this is to do depth first search and visit each edge only once. If the node connect the current element to its parent, we discard this route. Otherwise if this node connect to unvisited nodes or nodes on the stack, we mark the reverse direction. After first pass of DFS, the reverse graph can be found. Then we can perform dfs on the reversed graph to find the SCC.\n\nIt doesn\'t matter what direction we are assigning to each edge, if these nodes are strongly connected in both original and reverse directed graph, then it is in a cycle in the undirected graph. \n```\nclass Solution {\n    public List<List<Integer>> criticalConnections(int n, List<List<Integer>> connections) {\n        //build the adjacency list representation of the graph, graphR is the reversed graph\n        List<Integer>[] graphR = new ArrayList[n];\n        List<Integer>[] graph = new ArrayList[n];\n        for (int i = 0; i < n; ++i) {\n            graphR[i] = new ArrayList<Integer>();\n            graph[i] = new ArrayList<Integer>();\n        }\n        for (List<Integer> edge : connections) {\n            int from = edge.get(0), to = edge.get(1);\n            graph[from].add(to);\n            graph[to].add(from);\n        }\n        // use a linked list to store the reverse postorder of the depth first search\n        LinkedList<Integer> postorder = new LinkedList<>();\n        boolean[] visited = new boolean[n];\n        boolean[] onstack = new boolean[n];\n        dfs(graph, graphR, 0, -1, visited, onstack, postorder);\n        // perform second dfs on the reversed graph\n        int[] scc = new int[n];\n        Arrays.fill(visited, false);\n        int rank = 0;\n        for (int i : postorder) {\n            if (!visited[i]) {\n                dfsR(graphR, i, visited, scc, rank);\n                rank++;\n            }\n        }\n        // add all edges connecting different SCCs\n        List<List<Integer>> ans = new ArrayList<>();\n        for (List<Integer> edge : connections) {\n            int from = edge.get(0), to = edge.get(1);\n            if (scc[from] != scc[to]) {\n                ans.add(edge);\n            }\n        }\n        return ans;   \n    }\n    \n    private void dfs(List<Integer>[] graph, List<Integer>[] graphR, int cur, int par, boolean[] visited, boolean[] onstack, LinkedList<Integer> postorder) {\n        visited[cur] = true;\n        onstack[cur] = true;\n        for (int next : graph[cur]) {\n            if (next == par) continue;\n            if (onstack[next]) {\n                graphR[next].add(cur);\n            } \n            if (!visited[next]) {\n                graphR[next].add(cur);\n                dfs(graph, graphR, next, cur, visited, onstack, postorder);\n            }\n        }\n        onstack[cur] = false;\n        postorder.addFirst(cur);\n    }\n    \n    private void dfsR(List<Integer>[] graph, int cur, boolean[] visited, int[] scc, int rank) {\n        visited[cur] = true;\n        scc[cur] = rank;\n        for (int next : graph[cur]) {\n            if (!visited[next]) {\n                dfsR(graph, next, visited, scc, rank);\n            }\n        }\n    }   \n}\n```
[]