并查集

STA的阴谋
题目描述
有一天STA加了个实验室,为了庆祝,他买了块白板挂在自己的座位旁边。每天往上面写点奇怪的想法。

因此STA在实验室发呆的时候喜欢盯着白板,看看能不能把上面的想法关联起来。如果STA觉得两个想法有联系,就会把两个想法之间连一条线。那么显然,想法之间还可以通过别的想法间接关联起来。

于是STA偶尔也会思考,到底两个特定的想法之间是不是有关联的,无论是直接的,还是间接的。

但是STA的想法实在太多了。于是他决定给这些方法编个号,从1到n,然后写个程序来帮他处理这个事情。

当然STA不会把一个想法和自己关联起来,但还是可能会把两个想法重复关联起来,当然关联多次的话跟一次并无差别。

输入格式
第一行为两个整数n,m,表示STA最多会产生n个想法,以及会进行m次操作。 接下来为m行操作的指令,共分两种。 第一种

c 1 2
表示将编号为1和2的想法关联起来

第二种

q 1 2
表示查询编号为1和2的想法是否存在关联。

输出格式
对于每一个q指令产生一行输出。 如果两个想法存在关联,输出Connected!,如果不存在关联,输出Not connected!

样例输入
5 5
c 1 2
c 2 3
c 1 3
q 1 3
q 4 5
样例输出
Connected!
Not connected!
数据范围
10≤n≤1e6,n+1≤m≤7×n

思路:一道典型的并查集入门题。让我们一步步分析。
其实并查集就是一个认爸爸的过程
先建立一个数组f,用来储存儿子想法。f[1]=2的意思是,1的爹是2。
初始化f,使f[i]=i。

链接两个数

在连接时,如果一个人的爹不是自己
第一条请求:1和2连在一起
我们规定如果这样,就把左边的数作为右边的数的爹。
所以我们令f[2]=1.

第二条:2和3
同理,f[3]=2.

第三条:1和3
f[3]=1?但是我们发现f[3]=2.所以我们将f[2]的值修改为1(虽然本来就是),并顺便将f[3]的值也修改为1.
此时f[1],f[2],f[3]的值都为1,也就是说他们的爹都是1.

查询某两个数是否有链接

只需要看两个数是不是有同一个爹就行了。

上代码:

#include<stdio.h>
int f[1000005]={0};
int n,m,k;
void init()
{
    int i;
    for(i=1;i<=n;i++)   f[i]=i;
}

//找大爹的递归函数
int getdad(int v)
{
    if(f[v]==v) return v;//如果自己的爹就是自己,那他就是大爹
    else
    {
        f[v]=getdad(f[v]);//顺便把f[v]的值修改为大爹
        return f[v];
    }
}
void merge(int v,int u)//链接两个数
{
    int t1,t2;
    t1=getdad(v);
    t2=getdad(u);
    if(t1!=t2)  //如果不是同一个爹
    {
        f[t2]=t1;
        //“靠左”原则,左边变成右边的boss
        //即右边爹以及他的所有儿子们都变成左边爹的儿子
        //经过路径压缩后,将f[u]的爹的值也赋值为v的爹f[t1]
    }
}
int main()
{
    int i,x,y;
    scanf("%d %d",&n,&m);

    init();
    for(i=1;i<=m;i++)
    {
        getchar();
        char s;
        int x,y;
        scanf("%c%d%d",&s,&x,&y);
        if(s=='c')      merge(x,y);
        else if(s=='q')
        {
            int t1=getdad(x);
            int t2=getdad(y);
            if(t1==t2)  printf("Connected!\n");
            else    printf("Not connected!\n");
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值