并查集 求连通图问题
解题思路
并查集 ,重点在理解每个节点都要记录它的父亲节点
为节省查找时间,需要对路径进行压缩
如果当前节点能都与其他树合并 ,则应该讲集合总数减1
代码
class Solution {
public:
//利用并查集,字典: std::unordered_map , 倒树
//find merge add to tree
class CUnionFind
{
private:
std::unordered_map<int,int> tset;
int nConnectedCount=0;
public:
bool add(int x)
{
if(tset.count(x)==0)
{
tset[x] = -1;
nConnectedCount++;
return true;
}else
{
return false;
}
}
/// return root
int find(int x)
{
while(tset[x]!=-1 )
{
x= tset[x];
}
return x;
}
bool merge(int x,int y )
{
//4->9->2->-1 vs 7->-1
auto rootOfX = find(x);
auto rootOfY = find(y);
if(rootOfX == rootOfY) return false;
tset[rootOfX] = rootOfY;
nConnectedCount --; //如果非同根节点 才进行合并
//here need zip
//从下往上进行
// x -> parent x+1 -->parent
while(x != rootOfY)
{
int nextNode= tset[x];
tset[x]= rootOfY;
x= nextNode;
}
while(y != rootOfY )
{
int nextNode = tset[y];
tset[y] = rootOfY;
y= nextNode;
}
return true;
}
int getConnectedCount() {
return nConnectedCount;
}
void printTree()
{
for(auto x: tset)
{
std::cout << x.first <<":" << x.second <<", " ;
}
std::cout << std::endl;
}
};
int findCircleNum(vector<vector<int>>& isConnected) {
//e.g [[1,1,1],[1,1,1],[1,1,1]]
//output:
// 0:-1,
// 1:0, 0:-1,
// 2:0, 1:0, 0:-1,
//遍历每一行,tU.add
//如果发现有结合点 就合并
CUnionFind tU;
for(int i=0;i<isConnected.size();i++)
{
tU.add(i);
// std::cout << i << std::endl;
for(int j=0;j<i;j++)
{
if(isConnected[i][j]) tU.merge(i,j);
}
// tU.printTree();
}
return tU.getConnectedCount();
}
};
题目描述
- 省份数量
有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。
返回矩阵中 省份 的数量。