class Solution {
public:
vector<int> graph[100005];
void dfs(int currNode,
int parentNode,
int &timeStamp,
vector<bool> &vis,
vector<int> &tin,
vector<int> &low,
vector<vector<int>> &critical)
{
vis[currNode] = true;
tin[currNode] = low[currNode] = timeStamp++;
//Travel to neighbours
for(int i: graph[currNode]){
if(i==parentNode)
continue;
if(!vis[i]){
//Travel
dfs(i, currNode, timeStamp, vis, tin, low, critical);
low[currNode] = min(low[currNode], low[i]);
//Once it's back we can see if can be reached or not
if(low[i]>tin[currNode]){
critical.push_back({i, currNode});
}
}
else
low[currNode] = min(low[currNode], tin[i]);
}
}
vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) {
vector<int> tin(n, INT_MAX);
vector<int> low(n, INT_MAX);
vector<vector<int>> critical;
vector<bool> vis(n, false);
for(int i = 0; i<n; i++)
graph[i].clear();
for(auto i: connections){
graph[i[0]].push_back(i[1]);
graph[i[1]].push_back(i[0]);
}
for(int i = 0; i<n; i++){
if(!vis[i]){
int timeStamp = 0;
dfs(i, -1, timeStamp, vis, tin, low, critical);
}
}
return critical;
}
};