Koder / 박성훈
article thumbnail

간단한 유니온파인드 문제

유니온파인드에 관해서는 여름학교 수업 끝나고 정리하면서 글을 하나 작성할 계획이다.

이걸 보시는 분들은 아마 내 블로그에 유니온파인드 관련 글이 있을거다.

https://www.acmicpc.net/problem/1717

 

1717번: 집합의 표현

첫째 줄에 n(1 ≤ n ≤ 1,000,000), m(1 ≤ m ≤ 100,000)이 주어진다. m은 입력으로 주어지는 연산의 개수이다. 다음 m개의 줄에는 각각의 연산이 주어진다. 합집합은 0 a b의 형태로 입력이 주어진다. 이는

www.acmicpc.net

유니온파인드는 간단히 말하자면

자신의 부모만을 기억하는 구조다

그래서 부모 노드가 자기 자신인 노드의 경우에는 자기자신이 하나의 루트노드가 되는 것이고,

두 집합끼리 합할 때에는 그냥 루트노드 하나가 다른 루트노드의 자식노드가 되게 설계해주면 된다.

#include <stdio.h>

int parent[1000010] = {0};

int find(int k){
	if(k == parent[k]) return k;
	return parent[k] = find(parent[k]);
}

void union_f(int u, int v){
	int x = find(u);
	int y = find(v);
	if(x!=y) parent[x] = y;
	return;
}

int main(){
	int n,m,a,x,y;
	scanf("%d %d", &n, &m);
	
	for(int i=0; i<=n; i++) parent[i] = i;
	
	while(m--){
		scanf("%d %d %d", &a, &x, &y);
		if(!a) union_f(x,y);
		else{
			if(find(x)==find(y)) puts("YES");
			else	 			 puts("NO");
		}
	}
	return 0;
}

find(int k)가 자신이 포함된 트리의 루트노드를 찾는 함수이다.

자기자신이 부모인지를 확인해서, 자기자신이 부모이면 루트노드이므로 반환하고,

아닌경우에는 parent[k]에 루트노드의 값을 넣어주고 루트노드를 반환한다.

여기서 parent[k]에 루트노드의 값을 넣어주면

다음 find[k]의 과정이 더욱 더 빨라지기 때문에 이렇게 해주었다.

만약 parent[k]에 루트노드의 값을 넣어주지 않는다면

최대 시간복잡도는 O(N)에 해당한다.

union_f(int u, int v)는 두 트리를 합치는 소스코드이다

각자의 루트노드를 구한 다음

만약 둘의 루트노드가 같다면 이미 같은 트리상에 있으므로

굳이 합쳐줄필요가 없고

그렇지 않다면 하나의 트리가 다른 트리의 자식으로 들어간다.

두 원소가 같은 집합에 포함되어있는지 확인하는 방법은

하나의 트리는 반드시 루트노드를 단 하나 가지게 되므로

루트노드를 구해 비교했을때 같다면 같은 집합 내에 있는 것이다.

이렇게 잘 작성 해주면 무난하게 AC.

반응형