※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 4792번 문제인 레드 블루 스패닝 트리이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/4792
4792번: 레드 블루 스패닝 트리
무방향, 무가중치, 연결 그래프가 주어진다. 그래프의 각 간선은 빨간색 또는 파란색으로 색칠되어져 있다. 이 그래프의 스패닝 트리 중 파란색 간선이 정확히 k개인 것이 있는지 없는지 알아내
www.acmicpc.net
입력으로 연결그래프가 주어지므로, spanning tree가 포함되어있는 것은 자명하다.
노드가 N개인 그래프의 spanning tree는 N-1개의 edge를 가지게 된다.
이 문제를 해결하는 아이디어를 그대로 적는 대신, 풀이를 떠올릴 수 있는 관찰만을 기록해둘 것이다.
Kruskal(크루스칼) 알고리즘을 한 색깔의 에지들의 집합에 적용하면, 그 에지들을 이용하여 사이클이 없게끔 에지를 최대 몇 개 배치할 수 있는지 알 수 있다. 이 최대 개수의 배치에서 다른 그 색깔의 에지를 놓는다면 사이클이 생길 수밖에 없으므로, 이 배치를 포함하는 전체 그래프의 spanning tree의 나머지 에지는 다른 색깔의 에지로 채워지게 될 것이다. (그러한 spanning tree가 존재한다는 것은 조금 생각하면 알 수 있다.)
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
using namespace std;
int R[1001];
int B[1001];
void init(int N) {
for (int i = 1; i <= N; i++) {
R[i] = B[i] = i;
}
}
int findf_R(int x) {
if (x == R[x]) return x;
else return R[x] = findf_R(R[x]);
}
int findf_B(int x) {
if (x == B[x]) return x;
else return B[x] = findf_B(B[x]);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int N, M, K; cin >> N >> M >> K;
while (N != 0) {
init(N);
int cntR = 0, cntB = 0;
while (M--) {
char c; int f, t; cin >> c >> f >> t;
if (c == 'R') {
f = findf_R(f), t = findf_R(t);
if (f == t) continue;
cntR++;
R[t] = f;
}
else {
f = findf_B(f), t = findf_B(t);
if (f == t) continue;
cntB++;
B[t] = f;
}
}
if (N - 1 - cntR <= K && K <= cntB) cout << 1 << '\n';
else cout << 0 << '\n';
cin >> N >> M >> K;
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 16443 // C++] Bolinhas de Gude (0) | 2021.06.11 |
---|---|
[BOJ 18250 // C++] 철도 여행 (0) | 2021.06.10 |
[BOJ 2862 // C++] 수학 게임 (0) | 2021.06.08 |
[BOJ 1068 // C++] 트리 (0) | 2021.06.07 |
[BOJ 2647 // C++] 검은점과 하얀점 연결 (0) | 2021.06.06 |