Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Life Engineering

[BOJ 3830] 교수님은 기다리지 않는다 (C++) 본문

Problem Solving

[BOJ 3830] 교수님은 기다리지 않는다 (C++)

흑개 2021. 8. 18. 01:37

https://www.acmicpc.net/problem/3830

 

3830번: 교수님은 기다리지 않는다

교수님의 질문 (? a b)이 입력으로 들어올 때 마다, 지금까지 측정한 결과를 바탕으로 a와 b의 무게 차이를 계산할 수 있다면, b가 a보다 얼마나 무거운지를 출력한다. 무게의 차이의 절댓값이 1,000,

www.acmicpc.net

#include <bits/stdc++.h>
#define ll long long
using namespace std;

int parents[100001];
ll diff[100001];    //root 와의 차이

int find(int a){
    if (parents[a]==a){
        return a;
    }
    int p=find(parents[a]);
    diff[a]+=diff[parents[a]];      //갱신
    return parents[a]=p;
}

void union_(int a, int b, ll w){
    int pa=find(a);
    int pb=find(b);
    if (pa!=pb){
        diff[pb]=diff[a]-diff[b]+w;
        parents[pb]=pa;
    }
}

int main(){
    int N, M;
    char c;
    int a,b;
    ll w;
    vector<string> ans;
    cin>>N>>M;
    while (N!=0 || M!=0){
        for (int i=1; i<=N; i++){
            parents[i]=i;
            diff[i]=0;
        }
        for (int i=0; i<M; i++){
            cin>>c;
            if (c=='!'){
                cin>>a>>b>>w;
                union_(a,b,w);
            }
            else if (c=='?'){
                cin>>a>>b;
                if (find(a)!=find(b)){
                    ans.push_back("UNKNOWN");
                }
                else{
                    ans.push_back(to_string(diff[b]-diff[a]));
                }
            }
        }
        cin>>N>>M;
    }
    for (int i=0; i<ans.size(); i++){
        cout<<ans[i]<<"\n";
    }
    return 0;
}

2주 전에 특강에서 풀었던 문젠데 그때도 틀리고 지금 고민해봐도 안풀려서 해답 보고 풀었다. 플래티넘 넘사..

 

union-find 문제.. 근데 재귀를 곁들인..

 

diff는 root 노드와의 차이를 나타낸다. 

A 노드의 부모가 B 노드고, B 노드가 루트 노드인(자기 자신이 부모인) C를 가리키고 있을 때, 

A의 root 노드는 C가 된다. 근데 현재 diff[A]는 B와의 거리를 나타내므로, 부모 노드가 다른 노드를 부모로 삼고 가리키고 있을 때 같은 그룹에 속해서 차이를 알 수 있도록 해야된다. diff[B]를 diff[A]에다 더해서 루트 노드와의 최종 거리를 구해줘야 되는게 포인트다. find 함수에서 이상의 과정을 거치면서 루트 노드와의 차이가 diff 에 저장되며 갱신된다.

 

union 함수는 a노드는 pa와 diff[a] 만큼 차이, b 노드는 pb와 diff[b] 만큼 차이난다고 했을 때 pa와 pb 간의 거리는 다음과 같이 구해준다. 

pb의 루트는 이제 pa가 되었으므로, pb와 B는 -diff[B] 만큼 차이, B와 A는 w만큼 차이, A와 pa는 diff[A] 만큼 차이나므로 이를 모두 더해주면 diff[A]-diff[B]+w가 된다. 이 아이디어를 떠올리는게 힘든것같다..

 

pb 기준으로 diff 써진 애들은 나중에 find 호출하게 되면 pa의 루트인 pa 기준으로 다시 갱신된다.

 

'Problem Solving' 카테고리의 다른 글

[BOJ 1238] 파티 (C++)  (0) 2021.08.19
[BOJ 17070] 파이프 옮기기 (C++)  (0) 2021.08.19
[BOJ 2357] 최솟값과 최댓값 (C++)  (0) 2021.08.17
[BOJ 9466] 텀 프로젝트 (C++)  (0) 2021.08.17
[BOJ 2887] 행성 터널  (0) 2021.08.12