题目描述
解题思路
相当于把所有学生分成几个集合,每个集合里都是有friendship的同学,最后计算集合的个数,所以可以利用查并集去计算。
查Find:每个集合选一个代表元素,新加入的元素将自己的代表改为集合的代表,如果自己一个集合的话,自己可以代表自己。
并Union:对两个元素操作,如果发现两者代表元素一样,则属于同一集合;如果不是,则将其中一个元素的代表元素改为另一个元素的代表元素(有点绕,看下面的代码应该会明白很多)
代码
class Solution {
public:
#define MAX 202
struct DisJointSet{
int parent;//代表元素
int rank;
};
struct DisJointSet ds[MAX];
void init(){
for(int i=0;i<MAX;i++){
ds[i].parent = i;
ds[i].rank=1;
}
}
int find(int x){
if(ds[x].parent!=x)
ds[x].parent = find(ds[x].parent);//压缩路径优化
return ds[x].parent;
}
void _union(int x,int y){
x = find(x);
y = find(y);
if(x==y) return;
if(ds[x].rank>ds[y].rank){
ds[y].parent = x;
}else{
if(ds[x].rank==ds[y].rank)
ds[y].rank++;
ds[x].parent = y;
}
}
int findCircleNum(vector<vector<int>>& M) {
if(M.size()==0)
return 0;
init();
int row = M.size();
int col = M[0].size();
for(int i=0;i<row-1;i++){
for(int j=i+1;j<col;j++){
if(M[i][j])
_union(i,j);
}
}
int count=0;
for(int i=0;i<row;i++){
cout<<i<<" "<<ds[i].parent<<endl;
if(ds[i].parent==i){
count++;
}
}
return count;
}
};