LeetCoce1192. 查找集群内的关键连接
力扣数据中心有 n 台服务器,分别按从 0 到 n-1 的方式进行了编号。它们之间以 服务器到服务器 的形式相互连接组成了一个内部集群,连接是无向的。用 connections 表示集群网络,connections[i] = [a, b] 表示服务器 a 和 b 之间形成连接。任何服务器都可以直接或者间接地通过网络到达任何其他服务器。
关键连接 是在该集群中的重要连接,假如我们将它移除,便会导致某些服务器无法访问其他服务器。
请你以任意顺序返回该集群内的所有 关键连接 。
示例 1:
输入:n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]
输出:[[1,3]]
解释:[[3,1]] 也是正确的。
示例 2:
输入:n = 2, connections = [[0,1]]
输出:[[0,1]]
提示:
2 <= n <= 105
n - 1 <= connections.length <= 105
0 <= ai, bi <= n - 1
ai != bi
不存在重复的连接
代码
核心代码
class CNeiBo
{
public:
static vector<vector<int>> Two(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0)
{
vector<vector<int>> vNeiBo(n);
for (const auto& v : edges)
{
vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase);
if (!bDirect)
{
vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase);
}
}
return vNeiBo;
}
static vector<vector<std::pair<int, int>>> Three(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0)
{
vector<vector<std::pair<int, int>>> vNeiBo(n);
for (const auto& v : edges)
{
vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase, v[2]);
if (!bDirect)
{
vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase, v[2]);
}
}
return vNeiBo;
}
static vector<vector<int>> Grid(int rCount, int cCount, std::function<bool(int, int)> funVilidCur, std::function<bool(int, int)> funVilidNext)
{
vector<vector<int>> vNeiBo(rCount * cCount);
auto Move = [&](int preR, int preC, int r, int c)
{
if ((r < 0) || (r >= rCount))
{
return;
}
if ((c < 0) || (c >= cCount))
{
return;
}
if (funVilidCur(preR, preC) && funVilidNext(r, c))
{
vNeiBo[cCount * preR + preC].emplace_back(r * cCount + c);
}
};
for (int r = 0; r < rCount; r++)
{
for (int c = 0; c < cCount; c++)
{
Move(r, c, r + 1, c);
Move(r, c, r - 1, c);
Move(r, c, r, c + 1);
Move(r, c, r, c - 1);
}
}
return vNeiBo;
}
};
//割点
class CCutPoint
{
public:
CCutPoint(const vector<vector<int>>& vNeiB) : m_iSize(vNeiB.size())
{
m_vNodeToTime.assign(m_iSize, -1);
m_vCutNewRegion.resize(m_iSize);
}
void Init(const vector<vector<int>>& vNeiB)
{
for (int i = 0; i < m_iSize; i++)
{
if (-1 == m_vNodeToTime[i])
{
m_vRegionFirstTime.emplace_back(m_iTime);
dfs(vNeiB, i, -1);
}
}
}
const int m_iSize;
const vector<int>& Time()const { return m_vNodeToTime; }//各节点的时间戳
const vector<int>& RegionFirstTime()const { return m_vRegionFirstTime; }//各连通区域的最小时间戳
vector<bool> CalCut()const {
vector<bool> ret;
for (int i = 0; i < m_iSize; i++)
{
ret.emplace_back(m_vCutNewRegion[i].size());
}
return ret; }//
const vector < vector<pair<int, int>>>& NewRegion()const { return m_vCutNewRegion; };
protected:
int dfs(const vector<vector<int>>& vNeiB, const int cur, const int parent)
{
int iMinTime = m_vNodeToTime[cur] = m_iTime++;
OnBeginDFS(cur);
int iRegionCount = (-1 != parent);//根连通区域数量
for (const auto& next : vNeiB[cur]) {
if (next == parent)
{
continue;
}
if (-1 != m_vNodeToTime[next]) {
iMinTime = min(iMinTime, m_vNodeToTime[next]);
continue;
}
const int childMinTime = dfs(vNeiB, next, cur);
iMinTime = min(iMinTime, childMinTime);
if (childMinTime >= m_vNodeToTime[cur]) {
iRegionCount++;
m_vCutNewRegion[cur].emplace_back(m_vNodeToTime[next], m_iTime);
}
OnVisitNextEnd(childMinTime,cur, next);
}
if (iRegionCount < 2)
{
m_vCutNewRegion[cur].clear();
}
return iMinTime;
}
virtual void OnVisitNextEnd(int childMinTime,int cur, int next) {};
virtual void OnBeginDFS(int cur) {};
vector<int> m_vNodeToTime;
vector<int> m_vRegionFirstTime;
vector < vector<pair<int, int>>> m_vCutNewRegion; //m_vCutNewRegion[c]如果存在[left,r) 表示割掉c后,时间戳[left,r)的节点会形成新区域
int m_iTime = 0;
};
class CCutEdge : public CCutPoint
{
public:
using CCutPoint::CCutPoint;
vector<vector<int>> m_vCutEdges;
protected:
virtual void OnVisitNextEnd(int childMinTime, int cur, int next) override {
if (childMinTime > m_vNodeToTime[cur])
{
m_vCutEdges.emplace_back(vector<int>{ cur,next });
}
}
};
class Solution {
public:
vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) {
auto neiBo = CNeiBo::Two(n, connections, false);
CCutEdge cut(neiBo);
cut.Init(neiBo);
return cut.m_vCutEdges;
}
};
测试用例
template<class T, class T2>
void Assert(const T& t1, const T2& t2)
{
assert(t1 == t2);
}
template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}
}
int main()
{
int n;
vector<vector<int>> connections;
{
Solution sln;
n = 2, connections = { {0,1} };
auto res = sln.criticalConnections(n, connections);
Assert({ { 0,1} }, res);
}
{
Solution sln;
n = 4, connections = { {0,1},{1,2},{2,0},{1,3} };
auto res = sln.criticalConnections(n, connections);
Assert({ { 1,3} }, res);
}
}