题目描述:
There are n
servers numbered from 0
to n-1
connected by undirected server-to-server connections
forming a network where connections[i] = [a, b]
represents a connection between servers a
and b
. Any server can reach any other server directly or indirectly through the network.
A critical connection is a connection that, if removed, will make some server unable to reach some other server.
Return all critical connections in the network in any order.
Example 1:
Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]
Output: [[1,3]]
Explanation: [[3,1]] is also accepted.
Constraints:
1 <= n <= 10^5
n-1 <= connections.length <= 10^5
connections[i][0] != connections[i][1]
- There are no repeated connections.
class Solution {
public:
vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) {
// u是强连通分量的根的条件:u或u的子树不存在路径可以返回祖先
// 也就是low[u]<dfsnum[u]&&low[v]<dfsnum[u],v是u的子节点
num=0; // 节点访问编号
dfsnum=vector<int>(n+1,0); // dfsnum[i]表示访问该点的时间或编号,值越小表示越早访问到
low=vector<int>(n+1,0); // low[i]表示i或i的子树可以访问到的节点编号
visited=vector<bool>(n+1,false);
parent=vector<int>(n+1,-1);
for(auto connection:connections)
{
graph[connection[0]].push_back(connection[1]);
graph[connection[1]].push_back(connection[0]);
}
vector<vector<int>> result;
for(int i=1;i<=n;i++)
{
if(!visited[i]) tarjan(i,result);
}
return result;
}
void tarjan(int u, vector<vector<int>>& result)
{
visited[u]=true;
num++;
dfsnum[u]=low[u]=num;
for(int v: graph[u]) //访问所有出边
{
if(!visited[v]) //不曾访问过,可以认为是子节点了
{
parent[v]=u;
tarjan(v,result); // 递归访问子节点
low[u]=min(low[u],low[v]);
if(low[v]>dfsnum[u]) // 发现桥
result.push_back({min(u,v),max(u,v)});
}
else if(v!=parent[u]) // 注意判断是否存在回向边,排除重边
low[u]=min(low[u],dfsnum[v]);
}
}
private:
int num;
vector<int> dfsnum;
vector<int> low;
vector<bool> visited;
vector<int> parent;
unordered_map<int,vector<int>> graph;
};