개인사
[G3] 백준 1833번 고속철도 설계하기 C++ 정렬, 유니온 파인드, MST, 최소 스패닝 트리 본문
728x90

리뷰

https://www.acmicpc.net/problem/1833
엄청 오랜만에 풀어본 MST문제
전역 변수
- N : 배열의 최대 크기를 정의할 상수 변수
- arr : 간선 설치 비용을 저장할 2차원 정수 배열
- node : 집합 정보를 저장할 정수형 배열
- n : 노드의 개수를 저장할 변수
- Edge : 간선 정보를 정의할 구조체, 가중치를 기준으로 오름차순 정렬한다.
함수
1. Find
int Find(int a) {
if (node[a] == a) return a;
return node[a] = Find(node[a]);
}
노드가 속한 그룹의 번호를 반환하고, 경로 압축을 수행하기 위한 함수
2. Union
bool Union(int a, int b) {
int A = Find(a);
int B = Find(b);
if (A == B) return false;
node[B] = node[A];
return true;
}
두 노드가 속한 그룹의 번호를 비교하고, 합칠 수 있는지 여부를 반환하는 함수
문제풀이
- n값을 입력 받고, 변수 sum, cnt를 0으로 초기화한다.
- n*n크기의 인접 행렬을 입력 받아 arr배열을 초기화한다.
- 이때 입력값이 음수인 경우 양수로 전환해 sum에 더해주고, 값을 0으로 초기화한다.
- 인접 행렬로 인해 sum에는 간선 가중치가 두배로 인입되었으므로 2로 나누어준다.
- Edge타입 벡터 edges를 초기화 하고, 인접 행렬을 대각선으로 갈라 edges를 초기화해준다.
- sort함수를 통해 edges를 가중치 기준으로 오름차순 정렬해준다.
- pair<int, int>타입 벡터 conn을 초기화한다.
- node배열을 자기 자신의 인덱스를 값으로 갖도록 초기화한다.
- edges를 순회하며 간선 정보를 변수 f, t, w에 파싱한다.
- Union함수에 f, t를 매개변수로 전달하여 함수를 호출한다.
- Union함수의 반환값이 true인 경우 sum에 w를 더해주고, cnt를 증가시킨다.
- 만약 가중치가 0이 아닐 경우 conn애 {f, t}를 push해준다.
- cnt가 n-1에 도달한 경우 break처리해준다.
- sum과 conn.size()를 공백을 기준으로 출력하고, conn을 순회하며 개행문자를 삽입, pii정보를 공백을 기준으로 출력한다.
트러블 슈팅
없음
참고 사항
- 인접 행렬로 인해 sum에는 간선 가중치가 두배로 인입되었으므로 2로 나누어줬다.
- 간선의 가중치는 최대 1만이므로 int범위 내로 비용 계산이 가능하다.
정답 코드
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 201;
int arr[N][N];
int node[N];
int n;
struct Edge {
int f, t, w;
bool operator<(const Edge& other) const {
return w < other.w;
}
};
int Find(int a) {
if (node[a] == a) return a;
return node[a] = Find(node[a]);
}
bool Union(int a, int b) {
int A = Find(a);
int B = Find(b);
if (A == B) return false;
node[B] = node[A];
return true;
}
int main() {
cin >> n;
int sum = 0;
int cnt = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
cin >> arr[i][j];
if (arr[i][j] < 0) {
sum += -arr[i][j];
arr[i][j] = 0;
}
}
}
sum /= 2;
vector<Edge> edges;
for (int i = 1; i < n; ++i) {
for (int j = i + 1; j <= n; ++j) {
edges.push_back({ i, j, arr[i][j] });
}
}
sort(edges.begin(), edges.end());
vector<pair<int, int>> conn;
for (int i = 1; i <= n; ++i) node[i] = i;
for (const Edge& edge : edges) {
int f = edge.f, t = edge.t, w = edge.w;
if (Union(f, t)) {
sum += w;
++cnt;
if (w) conn.push_back({ f, t });
}
if (cnt == n - 1) break;
}
cout << sum << " " << conn.size();
for (const pair<int, int> pii : conn) {
cout << "\n" << pii.first << " " << pii.second;
}
}728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
| [G3] 백준 13905번 세부 C++ MST, 최소 스패닝 트리 (0) | 2026.02.25 |
|---|---|
| [G5] 백준 23843번 콘센트 C++ 정렬, 우선순위 큐, 그리디 알고리즘 (0) | 2026.02.24 |
| [S3] 백준 17952번 과제는 끝나지 않아! C++ 스택 (0) | 2026.02.19 |
| [G5] 백준 14217번 그래프 탐색 C++ 너비 우선 탐색, unordered_set (0) | 2026.02.18 |
| [G3] 백준 16441번 아기돼지와 늑대 C++ 너비 우선 탐색, 시뮬레이션 (0) | 2026.02.15 |
