halang-log
💡 PS

[BOJ] 1833 고속철도 설계하기

date
May 2, 2022
slug
boj-1833
author
status
Public
tags
PS
최소신장트리
summary
고속철도 설계하기 문제에 대한 풀이입니다.
type
Post
thumbnail
category
💡 PS
updatedAt
Aug 3, 2023 09:38 AM
언어

문제

풀이

MST(Minimum Spanning Tree) 문제이다.
처음에 prim방식으로 풀었는데 틀렸다. 그 이유를 생각해 보았는데, 이 문제 같은 경우 이미 지어진 고속철도가 있다. 비용은 들지만 이미 지어놨어서 이를 미리 고려해야 한다. 비용을 0이라고 가정하고 priority_queue를 돌렸지만, 생각해보면 비용이 0인 지점을 미리 고려해야 불필요한 소비를 막을 수 있다.
그래서 kruskal로 문제를 풀었다.
음수 간선은 비용을 더해주고 미리 merge한다. 이후 각 간선에 대한 비용을 정렬하여 가장 낮은 비용의 간선부터 루트 노드를 확인한다. 이후 find값이 서로 다를 경우 merge한다. 두 노드 번호는 pn 벡터에 저장한다.

코드

#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> using namespace std; typedef pair<int, int> pii; struct info { int cost; int s, e; }; int n; int p[200]; vector<info> arr; int ans = 0, tmp = 0; vector<pii> pn; int find(int a) { if (p[a] == -1) return a; return p[a] = find(p[a]); } void merge(int a, int b) { a = find(a), b = find(b); if (a == b) return; p[b] = a; } int main() { memset(p, -1, sizeof(p)); scanf("%d", &n); for(int i = 0; i < n; i++) { for(int a, j = 0; j < n; j++) { scanf("%d", &a); if (i >= j) continue; if (a < 0) { ans += abs(a); if (find(i) != find(j)) merge(i, j); } else arr.push_back({a, i, j}); } } sort(arr.begin(), arr.end(), [](info a, info b) {return a.cost < b.cost;}); for(int i = 0; i < arr.size(); i++) { if (find(arr[i].s) == find(arr[i].e)) continue; tmp++; merge(arr[i].s, arr[i].e); ans += arr[i].cost; pn.push_back({arr[i].s, arr[i].e}); } printf("%d %d\n", ans, tmp); for(pii i : pn) printf("%d %d\n", i.first+1, i.second+1); }