문제링크 : https://www.acmicpc.net/problem/18116
18116번: 로봇 조립
성규는 로봇을 조립해야 한다. 상자 안에는 여러 로봇의 부품들이 섞여 있다. 그런데 어떤 부품이 어느 로봇의 부품인지 표시가 되어있지 않다. 호재는 전자과라서 두 부품을 보면 같은 로봇의
www.acmicpc.net
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 987654321;
int N, M;
int parent[1000001];
int cnt[1000001];
int find_root(int x) //부모찾기
{
if(x == parent[x]) return x;
return parent[x] = find_root(parent[x]);
}
void Union(int a, int b) //병합
{
a=find_root(a);
b=find_root(b);
if(a!=b)
{
cnt[a]+=cnt[b]; //부모에 값을 연결함과 동시에 부모에 자식값 더해주기
parent[b]=a;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N;
for(int i=1; i<=1000000; i++) //초기화
{
parent[i]=i;
cnt[i]=1;
}
while(N--)
{
char c; int a, b;
cin >> c;
if(c=='I')
{
cin >> a >> b;
Union(a, b);
}
else
{
cin >> a;
cout << cnt[find_root(a)] << "\n"; //부모에 저장된 갯수 출력
}
}
}
살짝 응용된 분리집합 문제이다.
분리집합 알고리즘에서 병합과 부모 찾기만 필요하고, 이어졌는지 여부는 확인할 필요가 없으므로 해당 함수는 제거했다.
먼저 parent 배열을 초기화 할 때 갯수를 담을 cnt 배열도 같이 각 1로 초기화를 해준다.
이후 병합과정에서 값을 연결함과 동시에 부모쪽에 자식의 갯수를 더해준다.
이후 출력할때 출력할 부모의 총 갯수를 출력해주면 된다.
4
I 1 2
I 3 2
Q 1
cnt[1] += cnt[2] -> 2
cnt[3] += cnt[1(2의 부모)] -> 3
find_root(1) = 3
cnt[3] = 3
병합시 주의할 점은 병합 대상인 a와 b가 다를 때만 더해주는 작업을 해주어야 한다.
그렇지 않으면 이미 더해진 값이 또 더해지는 중복 상황이 발생한다.
6
I 1 2
I 1 3
I 2 3
Q 1
Q 2
Q 3
옳은 답 : 3 3 3
중복 발생 : 6 6 6
처음에 중복을 생각안하여 여러번 틀렸던 문제이다.
'백준 > 골드' 카테고리의 다른 글
[백준 5052번] 전화번호 목록 (C++) (0) | 2023.11.11 |
---|---|
[백준 14226번] 이모티콘 (C++) (0) | 2023.11.09 |
[백준 1717번] 집합의 표현 (C++) (0) | 2023.11.07 |
[백준 2133번] 타일 채우기 (C++) (0) | 2023.11.06 |
[백준 17073번] 나무 위의 빗물 (C++) (0) | 2023.11.04 |