Python Tarjan's O(V+E)
Any edge that is in a cycle is non-critical\n\n2. Hence, we need to find all edges that are not in a cycle\n\n3. How to represent cycles? We identify cycles by 
1. Any edge that is in a cycle is non-critical\n\n2. Hence, we need to find **all edges that are not in a cycle**\n\n3. How to represent cycles? We **identify cycles by its smallest-index node**, and keep track of which nodes are in which cycle via `lowest_rank`\n\n4. By default, all nodes belong to a different cycle, tracked in `rank`\n\n5. At every node, we shall :\n\n\t(a) Explore my neighbours\n\n\t(b) Update my `lowest_rank`, by checking against my neighbour\'s lowest rank\n\t\n\t(c) Check if I form a critical edge with my neighbour - iff my neighbour\'s lowest rank > my rank\n\t\n```\nclass Solution:\n    def criticalConnections(self, n: int, connections: List[List[int]]) -> List[List[int]]:\n        \n        # TRACK EACH NODE\'S RANK AND ITS LOWEST RANK\n        rank = [None] * n\n        lowest_rank = [None] * n\n        \n        # CREATE THE GRAPH\n        g = self.create_graph(connections)\n        \n        # DFS FROM NODE 0\n        critical = []\n        self.dfs(g, 0, None, set(), rank, lowest_rank, critical)\n        return critical\n        \n        \n    def dfs(self, g, curr, parent, vis, rank, lowest_rank, critical):\n        \n        # BASE CASE - NODE HAS BEEN VISITED\n        if curr in vis:\n            return\n        \n        # ADD TO VISITED\n        vis.add(curr)\n        \n        # SET THE NODE\'S RANK AND LOWEST RANK BY DEFAULT\n        rank[curr] = len(vis)\n        lowest_rank[curr] = len(vis)\n        \n        # EXPLORE ITS NEIGHBOURS\n        for nb in g.get(curr, []):\n            \n            # DO NOT EXPLORE THE NODE YOU CAME FROM\n            if nb == parent:\n                continue\n              \n            # EXPLORE MY NEIGHBOURS\n            self.dfs(g, nb, curr, vis, rank, lowest_rank, critical)\n            \n            # UPDATE MY LOWEST RANK\n            lowest_rank[curr] = min(lowest_rank[curr], lowest_rank[nb])\n            \n            # CHECK IF CRITICAL\n            if lowest_rank[nb] > rank[curr]:\n                critical.append([curr, nb])\n\n                    \n    def create_graph(self, connections):\n        g = defaultdict(list)\n        for c in connections:\n            g[c[0]].append(c[1])\n            g[c[1]].append(c[0])       \n        return g\n```
['Depth-First Search', 'Python3']