https://www.acmicpc.net/problem/4195
Union-Find 알고리즘을 응용한 문제 !
이 문제는 string 형태로 node가 주어진다. 따라서 이를 숫자 index로 치환해서 연산해야 한다. string 마다 고유한 int value값을 가지는 형태이므로 map을 사용해서 코드를 작성했다.
문제에서 정의한 친구 네트워크가 뭔지 이해가 안가서...🤷♀️ TC보고 일반화해서 풀었다
다만 일반적인 Union-Find와 다르게 이 문제는 연결된 노드들의 갯수를 찾기 위해 배열을 하나 더 정의해서 사용해야 했다. (매번 연결된 노드를 계산하면 시간초과 났다;;;)
현재 노드와 연결된 노드의 갯수(자기 자신 포함해서 초기값 1)로 정의되는 배열 cnt를 정의했고 두 노드가 merge될 때 마다 부모 index가 작은쪽으로 수를 몰아주도록 작성했다.
if(a<b) {
parents[b]=a;
cnt[a]+=cnt[b];
}
#include <iostream>
#include <map>
using namespace std;
const int MAX = 200001;
int T,n;
string str1, str2;
int parents[MAX];
int cnt[MAX];
int getParent(int x){
if(parents[x]==x) return x;
else return parents[x] = getParent(parents[x]);
}
void merge(int a, int b){
a = getParent(a);
b = getParent(b);
if(a==b) return ;
if(a<b) {
parents[b]=a;
cnt[a]+=cnt[b];
}
else {
parents[a]=b;
cnt[b]+=cnt[a];
}
}
bool isSame(int a, int b){
return getParent(a) == getParent(b);
}
int main(){
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>T;
while(T--){
cin>>n;
int index=1;
map<string, int> m;
fill(cnt, cnt+MAX, 0);
for(int i=0; i<n; i++){
cin>>str1>>str2;
if(m.count(str1)==0) {
m[str1]=index;
parents[index]=index;
cnt[index]=1;
index++;
}
if(m.count(str2)==0) {
m[str2]=index;
parents[index]=index;
cnt[index]=1;
index++;
}
int a = m[str1];
int b = m[str2];
if(isSame(a,b)){
cout<<cnt[getParent(a)]<<'\n';
}
else {
cout<<cnt[getParent(a)]+cnt[getParent(b)]<<'\n';
merge(a,b);
}
}
}
}