길민호(ethan.mino)
코딩수첩
길민호(ethan.mino)
전체 방문자
오늘
어제
  • 분류 전체보기 (215)
    • Computer Science (0)
    • Web (6)
      • CSS (0)
      • HTML (0)
    • Node.js (0)
    • Javascript (2)
    • Java (46)
      • Spring (27)
      • Jsp (0)
    • C\C++ (2)
    • Programming (0)
    • AI (0)
    • Database (7)
    • Git (5)
    • Algorithm (119)
      • Stack (0)
      • Queue (0)
      • Linked List (0)
      • Sort (0)
      • Simulation (27)
      • Recursion (0)
      • Backtracking (4)
      • Two Pointer (3)
      • Dynamic Programming (19)
      • Greedy (10)
      • Graph (3)
      • Dijkstra (1)
      • BFS\DFS (8)
      • Floyd (1)
      • MST (4)
      • Tree (4)
      • Binary Search (8)
      • Binary Search Tree (4)
    • IntelliJ (4)
    • Vscode (0)
    • Operating System (0)
    • 후기 (3)
    • 성장일지 (13)
    • 스터디 (7)
    • 설치 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ㅡ

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
길민호(ethan.mino)

코딩수첩

Algorithm/MST

[백준 1774번] 우주신과의 교감 (C++)

2022. 6. 8. 00:45

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

 

1774번: 우주신과의 교감

(1,1) (3,1) (2,3) (4,3) 이렇게 우주신들과 황선자씨의 좌표가 주어졌고 1번하고 4번이 연결되어 있다. 그렇다면 1번하고 2번을 잇는 통로를 만들고 3번하고 4번을 잇는 통로를 만들면 신들과 선자씨끼

www.acmicpc.net


우주신과의 교감 문제는 크루스칼/프림 알고리즘을 이용하여 해결할 수 있습니다.

 

이미 연결된 통로는 선택하고, 크루스칼이나 프림 알고리즘을 이용하여 나머지 간선을 선택하면 됩니다.

저는 크루스칼을 사용했습니다. 

 

⚠️ 주의할 점

  • 우주신의 좌표가 최대 1,000,000이므로, 거리를 계산할 때 1,000,000 * 1,000,000은 int형의 범위를 벗어날 수 있으므로 long long형을 사용해야합니다. 
  • 우주신 간의 거리가 실수가 될 수 있으므로, 거리를 저장하는 모든 변수의 타입은 double형이 되어야 합니다.

 

아래는 크루스칼과 Union Find를 사용한 코드입니다.

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

#define x first
#define y second

map<int, pair<int, int>> pos;
vector<int> p(1010, -1);
int n, m; 

int find(int x){    // x의 그룹의 Root를 반환
    if(p[x] < 0) return x;
    return p[x] = find(p[x]);
}

bool is_diff_g(int u, int v){   // u와 v가 같은 그룹이면 false를 반환, 다른 그룹이면 union을 수행한 뒤 true를 반환
    u = find(u), v = find(v);
    if(u == v) return false;
    if(u == v) p[u] = v;
    else p[v] = u;
    return true;
}

double dist(pair<int, int> pos1, pair<int, int> pos2){    // 좌표간의 거리를 반환
    long long a = pos1.x - pos2.x;
    long long b = pos1.y - pos2.y;

    return sqrt(a * a + b * b);
}

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

    cin >> n >> m;
    for(int x, y, i = 1; i <= n; i++){
        cin >> x >> y;
        pos[i] = {x, y};    // 각 우주신의 좌표를 저장
    }

    int cnt = 0;    // 선택한 edge의 개수
    for(int u, v, i = 0; i < m; i++){
        cin >> u >> v;
        if(!is_diff_g(u, v)) continue;  // u와 v가 같은 그룹인 경우 해당 edge를 선택하지 않음
        cnt++;  // edge 개수 증가
    }

    vector<tuple<double, int, int>> edges;
    for(int u = 1; u <= n; u++){    // 모든 우주신 간의 모든 edge를 생성
        for(int v = 1; v <= n; v++){
            if(u != v){
                pair<int, int> u_pos = pos[u];
                pair<int, int> v_pos = pos[v];

                double d = dist(u_pos, v_pos);  // 우주신간의 거리
                edges.push_back({d, u, v}); 
            }
        }
    }

    sort(edges.begin(), edges.end());   // 우주신 간의 거리를 기쥰으로 edge를 정렬

    double ans = 0; // 만들어야할 최소의 통로 길이
    for(int i = 0; i < edges.size(); i++){  // 크루스칼 수행
        double w, u, v;
        tie(w, u, v) = edges[i];
        
        if(!is_diff_g(u, v)) continue;
        ans += w;   // 우주신 간의 거리를 더해줌
        cnt++;  // 선택한 edge 개수 증가
        if(cnt == n - 1) break; // edge의 개수가 n - 1이 되면 모든 우주신이 연결된 것이므로 종료
    }
    
    cout << fixed;
    cout.precision(2);
    cout << ans << "\n";
}

 

아래는 문제 풀이에 사용된 테스트케이스입니다.

5 1
1 0
3 0
5 0
7 0
11 0
1 2
-> 8.00

5 4
1 0
3 0
5 0
7 0
11 0
1 2
2 3
3 4
4 5
-> 0.00

2 0
1000000 1000000
0 0
-> 1414213.56

 

 

'Algorithm > MST' 카테고리의 다른 글

[백준 10423번] 전기가 부족해 (C++)  (0) 2022.06.08
[백준 13418번] 학교 탐방하기 (C++)  (2) 2022.06.07
[백준 1647번] 도시 분할 계획 (C++)  (0) 2022.06.07
    'Algorithm/MST' 카테고리의 다른 글
    • [백준 10423번] 전기가 부족해 (C++)
    • [백준 13418번] 학교 탐방하기 (C++)
    • [백준 1647번] 도시 분할 계획 (C++)
    길민호(ethan.mino)
    길민호(ethan.mino)
    💻 호기심 많은 서버 개발자 길민호입니다.

    티스토리툴바