并查集
Posted xdblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集相关的知识,希望对你有一定的参考价值。
主要内容
本文主要记录并查集的基本实现方法,并逐步将一些例题填充到文章中。
并查集能做什么
并查集可以:
1. 合并集合
2. 查找两个元素是否在同一个集合内
3. 集合数量
4. 确定元素属于哪个集合。
完整代码示例
class UF
{
public:
UF();
UF(int N);
~UF();
bool isConnected(int p, int q);
int findRoot(int p);//查找根节点 主要函数
void unionSet(int p, int q);//合并集合 主要函数
int getSetCount();
int getElemCount();
private:
std::vector<int> m_parent;
std::vector<int> m_rank;
int m_setCount; //集合个数
int m_elemCount; //元素个数
};
UF::UF()
{
m_setCount = 0;
m_elemCount = 0;
}
UF::UF(int N):
m_setCount(N),
m_elemCount(N)
{
m_parent.resize(N);
m_rank.resize(N);
for(int i = 0; i < N; ++i)
{
m_parent[i] = i;
m_rank[i] = 1;
}
}
UF::~UF()
{
}
int UF::findRoot( int p )
{
if(p != m_parent[p])
{
m_parent[p] = findRoot(m_parent[p]);
}
return m_parent[p];
}
void UF::unionSet(int p, int q )
{
int rootOfP = findRoot(p);
int rootOfQ = findRoot(q);
if( rootOfP == rootOfQ )
return ;
if(m_rank[rootOfP] > m_rank[rootOfQ])
{
m_parent[rootOfQ] = rootOfP;
}
else
{
if(m_rank[rootOfP] == m_rank[rootOfQ])
{
m_rank[rootOfQ]++;
}
m_parent[rootOfP] = rootOfQ;
}
m_setCount--;
}
bool UF::isConnected( int p, int q)
{
return findRoot(p) == findRoot(q);
}
例题
LeetCode 547 朋友圈
班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。
给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。
示例 1:
输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出: 2
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回2。
示例 2:
输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出: 1
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。
注意:
N 在[1,200]的范围内。
对于所有学生,有M[i][i] = 1。
如果有M[i][j] = 1,则有M[j][i] = 1。
class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
N = M.size();
count = N;
parent.resize(count);
rank.resize(count);
for(int i = 0; i < N; i++)
{
parent[i] = i;
rank[i] = 1;
}
for(int i = 0; i < N -1 ; ++i)
{
for(int j = i + 1; j < N; ++j)
{
if(M[i][j] == 1)
{
uni(i,j);
}
}
}
return count;
}
int root(int p)
{
if(p != parent[p])
{
parent[p] = root(parent[p]);
}
return parent[p];
}
void uni(int p, int q)
{
int proot = root(p);
int qroot = root(q);
if(proot == qroot) return ;
if(rank[proot] > rank[qroot])
{
parent[qroot] = proot;
}
else
{
if(rank[proot] == rank[qroot])
{
rank[qroot]++;
}
parent[proot] = qroot;
}
count--;
}
int N;
vector<int> parent;
vector<int> rank;
int count;
};
以上是关于并查集的主要内容,如果未能解决你的问题,请参考以下文章