LeetCode 547 Friend Circles(并查集)

There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.

Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are directfriends with each other, otherwise not. And you have to output the total number of friend circles among all the students.

Example 1:

Input: 
[[1,1,0],
 [1,1,0],
 [0,0,1]]
Output: 2
Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. 
The 2
nd student himself is in a friend circle. So return 2.

Example 2:

Input: 
[[1,1,0],
 [1,1,1],
 [0,1,1]]
Output: 1
Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends, 
so the 0
th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1.

Note:

  1. N is in range [1,200].
  2. M[i][i] = 1 for all students.
  3. If M[i][j] = 1, then M[j][i] = 1.

题目大意:给出一个N*N的矩阵M,如果M[i][j]==1,说明i和j有直接朋友关系,如果M[i][j]==1并且M[j][k]==1那么i和k就有间接朋友关系。求所有人之间的朋友圈子有几个。

解题思路:利用并查集,把有有关系的人放到一个集合里,然后计算集合的个数。

代码如下:

struct DisjointSet{
    int par;
    int rank;
};
#define maxn 222
struct DisjointSet ds[maxn];

void init()
{
    for(int i = 0;i < maxn;i++){
        ds[i].par = i;
        ds[i].rank = 1;
    }
}

int find(int x)
{
    if(x == ds[x].par) return  x;
    return ds[x].par = find(ds[x].par);
}

void _union(int x, int y)
{
    x = find(x);
    y = find(y);
    if(x == y) return ;
    if(ds[x].rank < ds[y].rank)
        ds[x].par = y;
    else{
        if(ds[x].rank == ds[y].rank)
            ds[x].rank++;
        ds[y].par = x;
    }
}

int same(int x, int y)
{
    return find(x) == find(y);
}

int findCircleNum(int** M, int MRowSize, int MColSize) {
    init();
    for(int i = 0;i < MRowSize;i++){
        for(int j = i + 1;j < MColSize;j++){
            if(M[i][j] && M[j][i]) _union(i,j);
        }
    }
    int count = 0;
    for(int i = 0;i < MRowSize;i++){
        if(ds[i].par == i) count++;
    }
    return count;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值