레야몬
[C++] 4195번 친구 네트워크 - 자료 구조, 해시를 사용한 집합과 맵, 분리 집합 본문
1. 문제
- 두 사람의 친구 네트워크에 몇 명 있는지 구하는 프로그램을 작성하시오.
<입력>
- - 1 - 테스트 케이스의 개수 \(T(1 \leq T \leq 100,000)\)
- - F개의 줄 - 친구 관계가 생긴 순서대로 주어짐. 친구 관계는 두 사용자의 아이디로 이루어져 있으며 이는 알파벳 대문자 또는 소문자로만 이루어진 길이 20 이하의 문자열이다.
<출력>
- 친구 관계가 생길 때마다 두 사람의 친구 네트워크에 몇 명이 있는지 구하시오.
2. 재정의
- 집합의 원소 개수 구하기
3. 해결 방법
- unordered-map에 헤시를 써서~~
4. 실수한 점, 개선할 점
- MAX_F가 아니라 MAX_F*2개 만큼 배열을 잡아야 한다. 그 이유는 F개의 친구 관계가 나오므로 최대 친구의 수는 2*F이기 때문이다.
<코드>
#include <iostream>
#include <string.h>
#include <vector>
#include <unordered_map>
using namespace std;
const int MAX_F = 100001;
// <문제>
// 테스트 캐이스의 수 T, 친구 관계의 수 F
int T, F;
// <Union find>
// string idx를 int idx로 변환
unordered_map<string, int> hashmap;
// node의 index
int idx;
// 루트 노드 root[], 노드의 차수 node_rank[]
int root[2 * MAX_F], node_rank[2 * MAX_F];
// 한 집합에서 노드의 개수
int nodeCount[2 * MAX_F];
void input() {
cin >> F;
// 초기화
for(int i=0; i<2 * MAX_F; i++) {
root[i] = i;
node_rank[i] = 0;
nodeCount[i] = 1;
}
hashmap.clear();
idx = 0;
}
int find(int x) {
if(x == root[x])
return x;
else
// find연산 최적화
return root[x] = find(root[x]);
}
int Union(int x, int y) {
x = find(x), y = find(y);
// 두 값의 root가 같으면 합치지 않기
if(x == y)
return nodeCount[x];
// Union-by-rank 최적화
// 항상 높이가 더 낮은 트리를 높이가 높은 트리 밑에 넣는다.
if(node_rank[x] < node_rank[y]) {
root[x] = y;
nodeCount[y] += nodeCount[x];
return nodeCount[y];
}
else {
root[y] = x;
nodeCount[x] += nodeCount[y];
// 만약 트리의 높이가 같다면 합친 후 x의 높이 +1
if(node_rank[x] == node_rank[y])
node_rank[x]++;
return nodeCount[x];
}
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> T;
while(T--) {
input();
for(int i=0; i<F; i++) {
string s1, s2;
cin >> s1 >> s2;
// 아직 해시맵에 등록되지 않았을 경우 idx 만들어주기
if(!hashmap.count(s1))
hashmap[s1] = idx++;
if(!hashmap.count(s2))
hashmap[s2] = idx++;
//cout << hashmap[s1] << ' ' << hashmap[s2] << '\n';
cout << Union(hashmap[s1], hashmap[s2]) << '\n';
}
}
return 0;
}
<Union-find 알고리즘>
https://gmlwjd9405.github.io/2018/08/31/algorithm-union-find.html
[알고리즘] Union-Find 알고리즘 - Heee's Development Blog
Step by step goes a long way.
gmlwjd9405.github.io
<unordered_map>
https://math-coding.tistory.com/31
[Data Structure] unordered_map 사용법
C++ STL중 하나인 unordered_map에 대한 설명입니다. unorderd_map map보다 더 빠른 탐색을 하기 위한 자료구조입니다. unordered_map은 해쉬테이블로 구현한 자료구조로 탐색 시간복잡도는 O(1)입니다. map은 Bin
math-coding.tistory.com
<코드 바로가기>
https://www.acmicpc.net/problem/4195
4195번: 친구 네트워크
첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스의 첫째 줄에는 친구 관계의 수 F가 주어지며, 이 값은 100,000을 넘지 않는다. 다음 F개의 줄에는 친구 관계가 생긴 순서대로 주어진
www.acmicpc.net
※현재 고등학교 등교 중인 학생입니다. 이제 알고리즘을 본격적으로 공부하기 시작해서 아직 초보입니다. 혹시 제가 잘못 알고 있는 점이나 더 좋은 풀이 방법이 있어 댓글에 남겨주시면 감사히 하나하나 열심히 읽어보겠습니다. 좋아요, 단순한 댓글 한마디라도 저에겐 큰 힘이 됩니다! 감사합니다.
'알고리즘 > 백준' 카테고리의 다른 글
[C++] 1949번 우수 마을 - DP, 트리, 트리에서의 DP (0) | 2022.12.12 |
---|---|
[C++] 4386번 별자리 만들기 - 그래프 이론, 최소 스패닝 트리 (0) | 2022.12.12 |
[C++] 1717번 집합의 표현 - 자료 구조, 분리 집합 (0) | 2022.12.12 |
[C++] 1450번 냅색문제 - 이분 탐색, 중간에서 만나기 (0) | 2022.12.08 |
[C++] 9370번 미확인 도착지 - 그래프 이론, 데이크스트라 (0) | 2022.12.08 |