并查集

并查集是:擒贼先擒王原则和靠左原则,先有一个找祖先的函数,找祖先就需要递,当找到后就需要归,在归的过程中加上返回值就会把路程中的小子孙们都赋上祖先的值,最后把祖先的值输出。然后再根据靠左原则,进行合并

#include <stdio.h>
#include <stdlib.h>
int f[1000]={0},n,m,k,sum=0;
void init()
{
    int i;
    for(i=1;i<=n;i++)
    {
        f[i]=i;
    }
    return ;
}
int getf(int v)
{
    if(f[v]==v)
        return v;
    else
    {
        f[v]=getf(f[v]);//找祖先,一直找祖先,直到找到为止,这是递,归的时候因为有返回值,所以每次都会把返回值赋给上一层,最后在祖先旗下的所有孩子都会拥有祖先的值,并且最后输出的时候输出的也是祖先的值。
        return f[v];
    }
}
void merge(int v,int u)
{
    int t1,t2;
    t1=getf(v);
    t2=getf(u);
    if(t1!=t2)
        f[t2]=t1;
    return ;
}
int main()
{
    int i,x,y;
    scanf("%d%d",&n,&m);
    init();
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        merge(x,y);
    }
    for(i=1;i<=n;i++)
    {
        if(f[i]==i)sum++;
    }
    printf("%d\n",sum);
    return 0;
}

小结:进一步明白了递归,递归就是先递后归,在递的过程中一层层的往下走,同时所有的步骤都会在每一层中出现,到递结束后就是归了,归的话是先从最后一层把所有的函数执行完,该返回的就返回,然后回到上一层,继续依次执行这个这一层的每一个函数;就这个函数来举个栗子:

int getf(int v)
{
    if(f[v]==v)
        return v;
    else
    {
        f[v]=getf(f[v]);
        return f[v];
    }
}

当说2号和6号是同伙的时候,此时2号的老大是1号,1号的老大是5号,5号的老大是5号,先执行2号再来说6号,从2号开始进,不满足f[v]==v到达else,开始从1开始进,此时1号这一层有2个步骤,f[v]=getf(f[v]);
return f[v];
,1号也不满足,那就从5号开始进,也有2个步骤f[v]=getf(f[v]);
return f[v];
5号满足了,返回5号的值5,退回到上一层1的,把5赋值给f[1],并执行return f[1]=5,然后再退回到当一层2,把f[1]的值赋值给f[2],执行下一部返回f[2]的值5,这样就符合了在返回过程中把小子孙拥有的值改为祖先的值,其实是在归的过程实现的。
样例:
10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
输出值为3

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值