并查集

#include 
#include <string.h>
#define MAX_NODE 1001
int father[MAX_NODE]; // 记录父节点father[i]为i的根节点
int size[MAX_NODE]; // 记录树的大小
/*
    @function:  查找节点son的根节点
    @param:     son-->需要查找的节点
    @return:    int-->son节点的根节点
*/
int findFather(int son)
{
    if (father[son] != son) // son节点的父亲不是自己,说明son不是根节点
    {
        father[son] = findFather(father[son]); // 压缩路径
    }
    return father[son]; // 返回son的根节点
}
/*
    @function:  合并节点 p1 p2
    @param:     p1-->需合并的第一个点
                p2-->需合并的第二个点
    @return:    int-->需要合并返回1,不需要合并返回0
*/
int unionNode(int p1, int p2)
{
    int p1rt = findFather(p1); // 查找p1根节点
    int p2rt = findFather(p2); // 查找p2根节点
    if (p1rt == p2rt) // 根节点相同,不需要合并
    {
        return 0; // 返回0
    }
    if (size[p1rt] < size[p2rt]) // p1rt节点数小于p2rt
    {
        father[p1rt] = p2rt; // p1rt成为p2rt子树
        size[p2rt] += size[p1rt]; // p2rt节点数增加size[p1rt]个
    }
    else // p1rt节点数大于等于p2rt
    {
        father[p2rt] = p1rt; // p2rt成为p1rt子树
        size[p1rt] += size[p2rt]; // p1rt节点数增加size[p2rt]个
    }
    return 1;
}
/*
    @function:  初始化并查集
    @param:     sz-->并查集大小
    @return:    int-->初始化成功返回1,失败返回0
*/
int initUnionFind(int sz)
{
    if (sz >= MAX_NODE || sz < 0)
    {
        return 0;
    }
    for (int i = 0; i <= sz; ++i)
    {
        father[i] = i;
        size[i] = 1;
    }
    return 1;
}

int main()
{
    int n, m, s, t, cnt;
    while (scanf("%d%d", &n, &m) == 2)
    {
        if (initUnionFind(n))
        {
            cnt = 0;
            for (int i = 0; i < m; ++i)
            {
                scanf("%d%d", &s, &t);
                if (unionNode(s, t))
                {
                    cnt++;
                }
            }
            printf("连通块数量: %d\n", n - cnt);
        }
    }
    return 0;
}

你可能感兴趣的:(数据结构)