Tarjan Algorithm (DFS) Python Solution with explanation
In tarjan algorithm, we keep two arrays DFN and LOW in DFS procedure. DFN array records the order of DFS for each node while LOW array records the lowest order 
In tarjan algorithm, we keep two arrays DFN and LOW in DFS procedure. DFN array records the order of DFS for each node while LOW array records the lowest order of each node\'s neighbor except its direct parent. Initially, LOW[i] equals to DFN[i].\nAfter DFS, we find edge(u,v) where DFN(u)<LOW(v) and get the final answers. \n```\nfrom collections import defaultdict\n\nclass Solution(object):\n    def criticalConnections(self, n, connections):\n        """\n        :type n: int\n        :type connections: List[List[int]]\n        :rtype: List[List[int]]\n        """\n        graph = defaultdict(list)\n        for v in connections:\n            graph[v[0]].append(v[1])\n            graph[v[1]].append(v[0])\n            \n        dfn = [None for i in range(n)]\n        low = [None for i in range(n)]\n        \n        cur = 0\n        start = 0\n        res = []\n        self.cur = 0\n       \n        def dfs(node,parent):\n            if dfn[node] is None:\n                dfn[node] = self.cur\n                low[node] = self.cur\n                self.cur+=1\n                for n in graph[node]:\n                    if dfn[n] is None:\n                        dfs(n,node)\n                    \n                if parent is not None:\n                    l = min([low[i] for i in graph[node] if i!=parent]+[low[node]])\n                else:\n                    l = min(low[i] for i in graph[node]+[low[node]])\n                low[node] = l\n                \n        dfs(0,None)\n        \n        for v in connections:\n            if low[v[0]]>dfn[v[1]] or low[v[1]]>dfn[v[0]]:\n                res.append(v)\n        return res\n\n```
['Depth-First Search', 'Python']