길민호(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

[백준 13418번] 학교 탐방하기 (C++)

2022. 6. 7. 22:16

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

 

13418번: 학교 탐방하기

입력 데이터는 표준 입력을 사용한다. 입력은 1개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 건물의 개수 N(1 ≤ N ≤ 1,000)과 도로의 개수 M(1 ≤ M ≤ N(N-1)/2) 이 주어진다. 입력의 두 번

www.acmicpc.net


학교 탐방하기 문제는 크루스칼/프림 알고리즘을 이용하여 해결할 수 있습니다.

 

최대한 내리막길로 이동하면 피로도를 가장 줄일 수 있고, 최대한 오르막길로 이동하면 피로도를 높일 수 있습니다.

 

내리막길로 내려갔다 다시 올라올 때 오르막이 되는 경우는 고려하지 않아도 되기 때문에, 

오르막길의 비용을 내리막길보다 높게 설정하고, 최선의 경로를 파악할 때는 내리막길부터 선택하면 됩니다.

또한, 최악의 경로를 파악할 때는 오르막길부터 선택하면 됩니다.

 

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

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

#define MAX 1010
#define UP_HILL_WEIGHT 100

vector<int> p(MAX, -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;
}

int MST(vector<tuple<int, int, int>> edges){    // 크루스칼 수행
    fill(p.begin(), p.end(), -1);   // 각 정점이 속한 그룹의 root 초기화

    int up = 0, cnt = 0;    // up은 오르막길의 개수, cnt는 선택한 간선의 개수
    for(int i = 0; i < edges.size(); i++){
        int w, u, v;
        tie(w, u, v) = edges[i];    // 현재 확인하려는 간선

        if(!is_diff_g(u, v)) continue;  // u와 v가 같은 그룹이라면 continue
        if(w == UP_HILL_WEIGHT) up++;   // 오르막길의 개수 증가
        cnt++;  // 간선의 개수 증가
        if(cnt == n) break; // 입구를 포함하기 때문에, 간선의 개수가 n개가 되어야함
    }
    return up * up;
}

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

    cin >> n >> m;
    vector<tuple<int, int, int>> edges;

    for(int i =0; i < m + 1; i++){
        int u, v, c; cin >> u >> v >> c;
        int w = (c == 0) ? UP_HILL_WEIGHT : 1;  // 내리막길보다 오르막길의 비용을 높게 설정
        edges.push_back({w, u, v});
    }

    sort(edges.begin(), edges.end());   // 내리막길을 먼저 선택하도록 간선을 정렬
    int min_c = MST(edges);

    sort(edges.begin(), edges.end(), greater<>());  // 오르막길을 먼저 선택하도록 간선을 정렬
    int max_c = MST(edges);

    cout << max_c - min_c << "\n";  // 최악의 피로도 - 최선의 피로도
}

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

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

    티스토리툴바