백준 4195 (골드 2) 친구 네트워크 - 분리 집합 (Union Find)
2025. 7. 10. 16:46ㆍ개발/알고리즘
해당 문제는 그래프 탐색(DFS, BFS), 분리 집합을 활용해서 풀 수 있지만 그래프 탐색의 경우 시간 제한이 걸릴 수 있습니다.
만약 그래프로 푼다면 O(T * F * F)만큼이 걸릴 것 입니다. F의 최대 값이 100,000인데 F * F 라니 너무하지 않나요?
그래서 우리는 다른 방법을 찾아야 합니다.
바로 분리집합(Union Find) 입니다.
Union Find란 그래프에서 어떠한 정점들이 연결되어 있는지를 알고 싶을 때 사용한다고 생각하시면 되겠습니다.
아래에는 두 집합이 있습니다.
김병만 팀장의 팀원 -> 수아, 민지
박지원 팀장의 팀원 -> 종원, 민재
만약 수아와 민지가 같은 팀인지 종원과 민지는 같은 팀이 아닌지 컴퓨터는 어떻게 알 수 있을까요?
우리는 눈으로 단 번에 판단 할 수 있습니다. 하지만 팀원이 1 만명 10 만명이라면 눈으로 판단 할 수 있을까요?
Union Find 알고리즘에서는 팀장(Root)을 보고 같은 팀인지를 파악합니다.
수아의 root는 병만이고 민재의 root는 지원입니다. 서로 다른 root를 가졌으니 다른 집합인 것을 알 수 있습니다.
그리고 Union Find에서는 집합을 합치는 것도 간단합니다.
만약 병만이와 지원이의 팀을 합친다고 생각 해 봅시다.
하나의 집합을 다른 하나의 root를 가르치도록 변경하면 하나의 집합으로 합쳐지게 됩니다.
아래는 풀이 코드입니다.
#include <iostream>
#include <map>
using namespace std;
string findRoot(map<string, string>& hash, string& str)
{
if (hash.find(str) == hash.end())
{
return str;
}
return hash[str] = findRoot(hash, hash[str]);
}
int main()
{
int t, n;
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> t;
string str1, str2;
while (t--)
{
cin >> n;
map<string, string> friends;
map<string, int> counter;
while (n--)
{
cin >> str1 >> str2;
if (counter.find(str1) == counter.end())
{
counter[str1] = 1;
}
if (counter.find(str2) == counter.end())
{
counter[str2] = 1;
}
string root1, root2;
root1 = findRoot(friends,str1);
root2 = findRoot(friends, str2);
if (root1 != root2)
{
friends[root2] = root1;
counter[root1] += counter[root2];
}
cout<< counter[root1] << "\n";
}
}
}
'개발 > 알고리즘' 카테고리의 다른 글
백준 15918 (골드 5, 백트래킹) - 랭퍼든 수열쟁이야!! (2) | 2025.07.10 |
---|---|
골드 2 백준 (8-puzzle) 1525 (0) | 2025.06.24 |
프로그래머스 Lv1 - 서버 증설 횟수 (0) | 2025.06.15 |
최소 스패닝 트리 - MST (크루스칼 알고리즘), (프림 알고리즘) (0) | 2025.06.02 |
위상 정렬 - Topological Sort ) (1) | 2025.05.22 |