HRBUST2189 并查集入门 节点的连接

节点的连接

Time Limit: 1000 MS

Memory Limit: 32768 K

 

Total Submit: 80(43 users)

Total Accepted: 45(41 users)

Rating: 

Special Judge: No

Description

有N个节点,一开始任意两个节点都没有相连,之后有两种操作:

1: 将 A 节点和 B 节点连接起来。

2: 问从A节点出发可以直接或间接到达的节点数量。

如果 A 节点和 B 节点被连接起来了,那么从A可以到达B,同时从B也可以到达A。

Input

第一行是一个整数T,表示有T组测试数据。

对于每组测试数据,第一行是一个整数 n (n<=1000) 代表节点数,一个整数 m (m<=1000)代表操作数,之后有m行,每行代表一种操作。

第一种操作是:  0 A B  (1<=A,B<=n),表示将A,B节点连接起来;

第二种操作是:  1 A    (1<=A<=n),表示询问从A节点出发可以直接或间接到达的节点的数量。

Output

对于每组测试数据,如果是第二种操作,输出一个整数表示答案,每组输出占一行。

Sample Input

1

4 5

0 1

1 1 2

0 1

1 1 3

0 3

Sample Output

1

2

3

 

本题是一道简单的并查集问题

并查集主要就是有找到自己的上级 然后使两伙人合并到一伙

其中路径压缩是为使两伙归终于一个老大 而下级之间并不存在关心

 

本题没什么难的看看 代码注释就能理解

#include <stdio.h>

#include <algorithm>

#include <string.h>

#include <iostream>

using namespace std;

int pre[1050];

void nimabi(int x)   //这个算初始化(自己是自己的老大)

{

   for(int i=1;i<=x;i++)

    {

       pre[i]=i;

    }

}

int find (int x)  //找老大

{

   int r=x;

   while(r!=pre[r])

    {

       r=pre[r];

    }

   int i=x,j;    //每个人(除了老大)都只有一个老大(老大不会再有老大)

   while(i!=r)

    {

       j=pre[i];

       pre[i]=r;

       i=j;

    }

   return r;

}

void join(int x,int y)//这个算是两个集体合伙了(但是老大只能有一个)

{

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

   if(fx!=fy)

       pre[fx]=fy;

}

int main()

{

  int t;

  scanf("%d",&t);

  while(t--)

   {

      int n,m;

      scanf("%d%d",&n,&m);

      nimabi(n);

     /* for(int i=1;i<=n;i++)     //就是测试用来找老大的  便于理解

      printf("%d  ",find(i));

      printf("======\n");*/

      for(int i=0;i<m;i++)

      {

          int a;

          scanf("%d",&a);

          if(a==1)

          {

               int b,c;

              scanf("%d%d",&b,&c);

               join(b,c);

               /*for(int i=1;i<=n;i++)   //跟上面那个一个样

               printf("%d  ", find(i));

              printf("===========\n");*/

          }

          else

          {

               int d,sum=0;

               scanf("%d",&d);

               for(int j=1;j<=n;j++)

               {

                   if(find(d)==find(j)) sum++;

               }

               printf("%d\n",sum);

          }

      }

   }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值