并查集

来源:互联网 发布:c语言 用法 编辑:程序博客网 时间:2024/06/05 20:34

最近老是遇到处理类似集合,判联通块的问题,一直没有一个好的方法,问过一次jinzeyu有并查集这东西,昨天晚上又遇见,就查了查怎么用就记录一下。

一篇讲并查集很好的博文点击打开链接

就是通过一个记录前驱的数组把属于一个集的都连起来,集的代表元就是根节点。

int pre[1000 ];

int find(int x)                                                                                                         //查找根节点

    int r=x;

    while ( pre[r ] != r )                                                                                              //返回根节点 r

          r=pre[r ];

 

    int i=x , j ;

    while( i != r )                                                                                                        //路径压缩

    {

         j = pre[ i ]; // 在改变上级之前用临时变量  j 记录下他的值 

         pre[ i ]= r ; //把上级改为根节点

         i=j;

    }

    return r ;

}

 

 

void join(int x,int y)                                                                                                    //判断x y是否连通,

                                                                                             //如果已经连通,就不用管了 //如果不连通,就把它们所在的连通分支合并起,

{

    int fx=find(x),fy=find(y);

    if(fx!=fy)

        pre[fx ]=fy;

}

昨天在pat上的一道题目

朋友圈   (25分)

某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。

输入格式:

输入的第一行包含两个正整数N(\le30000)和M(\le1000),分别代表学校的学生总数和俱乐部的个数。后面的M行每行按以下格式给出1个俱乐部的信息,其中学生从1~N编号:

第i个俱乐部的人数Mi(空格)学生1(空格)学生2 … 学生Mi

输出格式:

输出给出一个整数,表示在最大朋友圈中有多少人。

输入样例:

7 43 1 2 32 1 43 5 6 71 6

输出样例:

4

最后要输出最大朋友圈的人数,再加一个数组记录一个朋友圈的人数在join的时候,更新相应的数量,就是加上合并过来的朋友圈的人数。

#include<bits/stdc++.h>using namespace std;int pre[30010];int cnt[30010]; //记录数量int tfind(int r){    int i=r;    while(pre[i]!=i)        i=pre[i];    int x=r,j;    while(pre[x]!=i)    {        j=pre[x];        pre[x]=i;        x=j;    }    return i;}void join(int x,int y){    int fx=tfind(x),fy=tfind(y);    if(fx!=fy)    {        pre[fy]=fx;        cnt[fx]+=cnt[fy]; //更新,加上合并过来朋友圈的人数    }    return ;}int main(){    int n,m;    int tmp,x,y;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        pre[i]=i;        cnt[i]=1;    }    for(int i=1;i<=m;i++)    {        scanf("%d",&y);        for(int j=1;j<=y;j++)        {            scanf("%d",&x);            if(j==1)                tmp=x;            else            {                join(tmp,x);            }        }    }    int tmax=0;    for(int i=1;i<=n;i++)    {        if(cnt[i]>tmax)            tmax=cnt[i];    }    printf("%d",tmax);    return 0;}


0 0