C++ Easiest Solution using Tarjan's Algorithm [1 DFS Traversal] O(V+E)
Just One Simple Thing: Critical connection is that edge between parent vertex and child vertex in DFS tree for which the minimum discovery time of child vertex 
**Just One Simple Thing**: *Critical connection is that edge between parent vertex and child vertex in DFS tree for which the minimum discovery time of child vertex is greater than discovery time of parent vertex.* Now you must be wondering a child will always have greater discovery time but what about back edges. Think ;)\n**Discovery time**: It is when the vertex is called in DFS call stack.\n\n```\nif(low[v]>disc[u]{\n//this is a critical connection\n}\n```\n\n**Implementation:**\n\nWe use 4 arrays:\n\n***bool visited[]*** : For checking if vertex is visited or not.\n**discovery time**(*int disc[]*) : For storing discovery time which stores when the vertex will be visited in DFS tree.\n**Low values**(*int low[]*): For storing low values which stores the smallest discovery time among vertex and all its adjacents. This is the only cool thing int this algorithm.\n***Parent***(*int parent[]*): So as we are working on undirected graph but in traversal we don\'t want to traverse bidirectional edges we only want to traverse through tree edges. \n\n```\nclass Solution {\npublic:\n    void dfsutil(int u,bool visited[],int disc[],int low[],int parent[],vector<vector<int>>& ans,vector<vector<int>>& graph){\n        static int time=0;\n        visited[u]=true;\n\t\t//discovery time increment\n        disc[u]=low[u]=++time;\n\t\t//for every adjacent\n        for(auto v:graph[u]){    \n\t\t//if not visited\n            if(!visited[v]){\n                parent[v]=u;\n                dfsutil(v,visited,disc,low,parent,ans,graph);\n\t\t\t\t//if any adjacent has less dicovery time then update in me also(parent is saying to adjacents)\n                low[u]=min(low[u],low[v]);\n\t\t\t\t//only condition for critical connection\n                if(low[v]>disc[u])\n                    ans.push_back({u,v});\n                \n            }\n\t\t\t//if visited but not parent then decrease discovery time if possible\n\t\t\telse if(v!=parent[u]){\n                low[u]=min(low[u],disc[v]);\n            }\n        }\n    }\n    void dfs(int n, vector<vector<int>>& ans,vector<vector<int>>& graph){\n        bool* visited = new bool[n];\n        int* disc = new int[n];\n        int* low = new int[n];\n        int* parent = new int[n];\n\t\t//initializing arrays\n        for(int i=0;i<n;++i){\n            visited[i]=false;\n            parent[i]=-1;\n        }\n\t\t//dfs\n        for(int i=0;i<n;++i){\n            if(visited[i]==false)\n                dfsutil(i,visited,disc,low,parent,ans,graph);\n        }\n    }\n    vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) {\n        vector<vector<int>> ans;\n        vector<vector<int>> graph(n);\n\t\t//making graph\n        for(auto x: connections){\n            graph[x[0]].push_back(x[1]);\n            graph[x[1]].push_back(x[0]);\n        }\n\t\t//calling dfs\n        dfs(n,ans,graph);\n        return ans;\n    }\n};\n```
[]