문제
https://www.acmicpc.net/problem/23594
정점이 $N$개인 그래프를 구성하려 한다.
그래프 상에서 서로 이동 가능해서는 안되는 정점 쌍이 $K$개 주어지고, 그래프에 사용할 후보 간선이 $M$개 주어진다.
후보 간선들을 주어진 순서대로 하나씩 보면서, 그래프 상에 존재해도 되는 간선이면 사용하고 그렇지 않다면 그냥 넘어간다.
이 때, 사용되는 간선들을 모두 구해야 한다.
풀이
각 정점별로, 해당 정점에서 갈 수 있는 정점들의 목록 $V$와, 해당 정점으로부터 도달해서는 안되는 정점의 목록 $S$를 정의하고 관리해보자.
후보 간선들 중, 현재 보고있는 간선을 $(a,b)$라고 하자.
정점 $a$와 $b$가 그래프 상에서 이미 서로에게 도달 가능한 상태이면, 해당 간선은 당연히 사용 가능하다.
그렇지 않다면, 이 간선을 추가했을 때 $V[a]$에 존재하는 어떤 점 $x$가 $S[b]$에도 존재한다면, 문제 조건에 위배되기 때문에 이 간선은 사용할 수 없다.
마찬가지로, $V[b]$에 존재하는 어떤 점 $y$가 $S[a]$에도 존재한다면 이 간선은 사용할 수 없다.
그렇지 않다면, 간선을 사용할 수 있으므로 잘 보관해놓고 있자.
정리하면, 해결해야 하는 부분이 두 가지 있다.
1. 정점 $a$와 $b$가 그래프 상에서 서로 도달 가능한 상태인지 확인하기
$\rightarrow$ 분리 집합으로 판별할 수 있다.
2. $V$와 $S$ 관리하기
$\rightarrow$ 어차피 간선 $(a,b)$에 대해 분리 집합으로 각자의 루트만 가져올거면, 같은 집합에 속하는 정점들 끼리는 모두 $V$와 $S$가 같기 때문에 여러 개를 관리할 필요가 없어진다. union할 때 smaller to larger로 $V$와 $S$를 집합의 루트가 될 정점에게 쥐어주면 된다.
#include <iostream>
#include <set>
#include <functional>
using namespace std;
set<int> S[100001]{};
vector<int> V[100001]{};
int r[100001]{};
int main() {
cin.tie(0)->sync_with_stdio(0);
int N, K, M;
cin >> N >> K >> M;
for (int i = 1; i <= N; i++) V[i].push_back(i), r[i] = i;
function<int(int)> f = [&](int x) -> int { return x == r[x] ? x : r[x] = f(r[x]); };
for (int a,b; K--;) {
cin >> a >> b;
S[a].insert(b);
S[b].insert(a);
}
vector<int> ans;
for (int a, b, i = 1; M--; i++) {
cin >> a >> b;
int x = f(a), y = f(b);
if (x == y) {
ans.push_back(i);
continue;
}
bool flag = 1;
int small = V[x].size() < V[y].size() ? x : y;
int big = small == x ? y : x;
for (int k : V[small]) {
if (S[big].count(k)) { flag = 0; break; }
}
if (!flag) continue;
ans.push_back(i);
if (V[x].size() > V[y].size()) swap(V[x], V[y]);
for (int k : V[x]) V[y].push_back(k);
V[x] = vector<int>();
if (S[x].size() > S[y].size()) swap(S[x], S[y]);
for (int k : S[x]) S[y].insert(k);
S[x] = set<int>();
r[x] = y;
}
cout << ans.size() << '\n';
for (int i : ans) cout << i << ' ';
}'문제 풀이' 카테고리의 다른 글
| BOJ 17471 - 게리맨더링 [C++] (0) | 2025.01.23 |
|---|---|
| BOJ 12928 - 트리와 경로의 길이 [Java] (0) | 2025.01.23 |
| BOJ 13215 - Fish [C++] (0) | 2025.01.22 |
| BOJ 20127 - Y-수열 [C++] (1) | 2025.01.22 |
| BOJ 13244 - Tree [C++] (1) | 2025.01.22 |