※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 9344번 문제인 도로이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/9344
9344번: 도로
어떤 나라에는 1부터 N까지 이름 붙여진 N개의 도시가 있다. 한 엔지니어는 모든 도시를 연결하는 도로를 건설하고자 한다. 즉, 모든 도시에 대해 항상 다른 어떤 도시로든 이동할 수 있어야 한다
www.acmicpc.net
각 테스트케이스 별로 그래프에서 특정 에지가 MST(최소 신장 트리)에 포함될 수 있는지 판별할 것을 요구하는 문제이다.
주어지는 그래프의 MST는 유일하지 않으므로 MST를 크루스칼 알고리즘(Kruskal's Algorithm), 프림 알고리즘(Prim's Algorithm)등으로 아무거나 하나 구해 대조하는 것만으로는 문제를 해결할 수 없다. 모든 에지의 가중치가 같은 완전그래프를 생각해 보면 이는 간단하게 이해할 수 있을 것이다.
이 문제를 해결하는 방법은 여러 가지가 있다. 이 글에서는 그 중 두 가지를 간략하게 소개한다.
1. 크루스칼 알고리즘(Kruskal's Algorithm)의 변형
크루스칼 알고리즘에서 각 에지를 살펴 MST에 추가할 수 있다는 것을 확인 후 해당 에지를 바로 MST에 추가하는 대신 같은 가중치의 에지들을 묶어 각각 MST에 추가할 수 있는지 따로 확인한 다음 그 에지 중 추가할 수 있는 에지들을 MST에 추가하는 방법이다.
2. 주어진 그래프의 MST를 구성하는 비용과 주어진 에지를 우선적으로 먼저 집어넣고 나머지 노드를 최소비용으로 합쳤을 때의 비용을 구한 다음 두 값이 같은지 대조
글쓴이는 1번 방법을 구현하여 문제를 해결했다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int T, N, M, P, Q;
int arr[10001];
int findf(int x) {
if (arr[x] == x) return x;
return arr[x] = findf(arr[x]);
}
vector<pair<int, pair<int, int>>> E;
void solve() {
E.clear();
cin >> N >> M >> P >> Q;
if (P > Q) swap(P, Q);
auto PP = make_pair(P, Q);
while (M--) {
int x, y, w; cin >> x >> y >> w;
if (x > y) swap(x, y);
E.emplace_back(make_pair(w, make_pair(x, y)));
}
sort(E.begin(), E.end());
for (int i = 1; i <= N; i++) arr[i] = i;
int old = -1; vector<pair<int, int>> tmp;
for (auto &p : E) {
if (old < p.first) {
for (auto &pp : tmp) {
int x = findf(pp.first), y = findf(pp.second);
if (x != y) arr[y] = x;
}
old = p.first;
tmp.clear();
}
int x = findf(p.second.first), y = findf(p.second.second);
if (x != y) {
if (p.second == PP) {
cout << "YES\n";
return;
}
tmp.emplace_back(p.second);
}
}
cout << "NO\n";
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> T;
while (T--) solve();
}
'BOJ' 카테고리의 다른 글
[BOJ 29812 // C++] 아니 이게 왜 안 돼 (0) | 2024.03.01 |
---|---|
[BOJ 24504 // C++] blobcry (1) | 2024.02.29 |
[BOJ 30646 // C++] 최대 합 순서쌍의 개수 (1) | 2024.02.27 |
[BOJ 30644 // C++] 띠 정렬하기 (0) | 2024.02.26 |
[BOJ 14446 // C++] Promotion Counting (1) | 2024.02.25 |