【Quick-Find算法】

原理

  • 基于染色思想,一开始每个人都是自己的颜色
  • 连接两个点时,把两个点设置成一个颜色
  • 如果两个点颜色一样,说明是一伙的,否则不是

一、问题描述

所谓一个朋友圈子,不一定其中的人都相互认识。
例如:小明的朋友是小李,小李的朋友是小于,那么他们三个人属于一个朋友圈。

现在给出一些人的朋友关系,人按照从1到 n n n编号,在这中间会进行询问某两个人是否属于一个朋友圈,请你编写程序,实现这个过程。


输入格式

第一行两个整数, n n n m m m ( 1 (1 (1 ≤ \leq n n n ≤ \leq 10000 10000 10000 , 3 ≤ 3\leq 3 m m m ≤ \leq 100000 ) ) ),分别表示人物和操作数。

接下来有 m m m行,每行三个整数 a , b , c , ( a ⊂ [ 1 , 2 ] , 1 ≤ b , c ≤ n ) a,b,c,(a\subset[1,2],1 \leq b,c \leq n) a,b,c,(a[1,2],1b,cn)
1.当 a = 1 a=1 a=1时,代表新增一条已知信息, b , c b,c b,c是朋友
2.当 a = 2 a=2 a=2时,代表根据以上消息,询问 b , c b,c b,c是否是朋友

输出格式

对于每个 a = 2 a=2 a=2的操作,输出 [ Y e s ] [Yes] [Yes] [ N o ] [No] [No]代表询问的两个人是否是朋友关系。

  • List item
输入样例
6 5
1 1 2
2 1 3
1 2 4
1 4 3
2 1 3
输出样例:
No
Yes

代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

typedef struct UnionSet{
	int *color;
	int size;
}UnionSet;

UnionSet *initSet(int n){
	UnionSet *u = (UnionSet *)malloc(sizeof(UnionSet));
	u->color = (int *)malloc(sizeof(int)*(n+1));
	u->size = n+1;
	int i;
	for(i = 0; i < u->size; i++)
	    u->color [i] = i;
	    
	return u;
}
//判断颜色 
int find(UnionSet *u,int idx){
	return u->color[idx];
} 
//合并
int merge(UnionSet *u,int a,int b){
	if(find(u,a)==find(u,b))
	    return 0;
	int acolor = find(u,a);
	int i;
	for(i=0;i<u->size;i++){
		if(find(u,i)==acolor)
		    u->color[i] = u->color [b];
	}
	return 1;
} 

void freeUnion(UnionSet *u){
	if(!u)
        return ;
    
    free(u->color);
    free(u);
}
int main(){
	int n,m,i;
	scanf("%d %d",&n,&m);
	UnionSet *u = initSet(n);
	
	for(i=0;i<m;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		switch(a){
			case 1:
				merge(u,b,c);
				break;
			case 2:
				printf("%s\n",find(u,b)==find(u,c)?"Yes":"No");
				break;
		}
	}
	return 0;
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值