본문으로 바로가기

백준 04195 - 친구 네트워크

category BOJ 백준/기타 2020. 11. 26. 11:42

출처 : https://www.acmicpc.net/problem/4195 

 

4195번: 친구 네트워크

첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스의 첫째 줄에는 친구 관계의 수 F가 주어지며, 이 값은 100,000을 넘지 않는다. 다음 F개의 줄에는 친구 관계가 생긴 순서대로 주어진

www.acmicpc.net

 

고려사항

  • 유니온 파인드 문제.
  • map<이름, 집합번호> 를 통해 각각의 이름에 idx를 부여하여 유니온 파인드 알고리즘을 적용.
  • vector<pair<루트 집합, 구성원 수>> 로 union 시에 구성원 수를 같이 업데이트 해주고 그 값을 반환하면 됨.
  • 원래 유니온 파인드에서는 같은 루트를 지닌 즉, 같은 집합에 속해 있으면 어느 곳을 업데이트 해줘도
    크게 상관이 없기 때문에, 보통 23 라인부터는 else로 묶는데
    이 알고리즘으로는 같은 집합이 합쳐져서 구성원 수 변경이 없는데도, *2 가 되어버린다.
    따라서 같은 집합에 속해 있으면 바로 반환하도록 따록 else 문을 구성한다.

 

#include <iostream>
#include <vector>
#include <map>
using namespace std;

int findSet(vector<pair<int, int>> &v, int set){
    if(set == v[set].first){
        return set;
    }

    v[set].first = findSet(v, v[set].first);
    return v[set].first;
}

int unionSet(vector<pair<int, int>> &v, int set1, int set2){
    int parent1 = findSet(v, set1);
    int parent2 = findSet(v, set2);

    if(parent1 < parent2){
        v[parent2].first = parent1;
        v[parent1].second += v[parent2].second;
        return v[parent1].second;
    }else if(parent1 > parent2){
        v[parent1].first = parent2;
        v[parent2].second += v[parent1].second;
        return v[parent2].second;
    }else{
        return v[parent1].second;
    }
}

int main() {
    cin.tie(NULL);
    ios::sync_with_stdio(false);

    int t, n, idx, set1, set2;
    string name1, name2;

    cin>>t;
    for(int p=0;p<t;++p){
        cin>>n;
        idx = 1;

        map<string, int> m;
        vector<pair<int, int>> v(1,{0,0});
        for(int i=0;i<n;++i){
            cin>>name1>>name2;
            if(m.find(name1) == m.end()){
                m[name1] = idx;
                v.push_back({idx, 1});
                set1 = idx++;
            }else{
                set1 = m[name1];
            }

            if(m.find(name2) == m.end()){
                m[name2] = idx;
                v.push_back({idx, 1});
                set2 = idx++;
            }else{
                set2 = m[name2];
            }

            cout<<unionSet(v, set1, set2)<<"\n";
        }
    }

    return 0;
}

'BOJ 백준 > 기타' 카테고리의 다른 글

백준 02609 - 최대공약수와 최소공배수  (0) 2020.12.18
백준 02252 - 줄 세우기  (0) 2020.11.27
백준 11438 - LCA 2  (0) 2020.11.25
백준 01976 - 여행 가자  (0) 2020.11.23
백준 02108 - 통계학  (0) 2020.11.22