节点的连接 | ||||||
| ||||||
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);
}
}
}
}