※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 18133번 문제인 가톨릭대학교에 워터 슬라이드를??이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/18133
18133번: 가톨릭대학교에 워터 슬라이드를??
두 정수 N (2 ≤ N ≤ 100,000), M (1 ≤ M ≤ 100,000)이 주어진다. N 은 건물의 개수를, M 은 터널의 개수를 나타낸다. 건물 옥상들의 번호는 1과 N 사이의 정수다. 다음 M개의 줄에는 각각 두 정
www.acmicpc.net
주어진 문제의 상황을 건물을 노드로, 터널을 방향이 있는 에지로 보아 그래프로 모델링하자.
같은 SCC 내에 속한 노드들은 서로 방문했다가 다시 자기 자신으로 돌아올 수 있다는 성질이 있음을 상기하자. 이를 이용해 주어진 그래프의 각 SCC를 노드로 하는 condensation graph의 indegree가 0인 노드의 개수를 세는 것으로 문제를 해결할 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
using namespace std;
int N, M;
vector<int> G[100001];
int dfi[100001];
int dfidx = 1;
int ndi[100001];
int ndidx = 1;
vector<int> stk;
int dfs(int cur) {
stk.emplace_back(cur);
int ret = dfi[cur] = dfidx++;
for (auto& x : G[cur]) {
if (dfi[x]) {
if (!ndi[x]) ret = min(ret, dfi[x]);
}
else ret = min(ret, dfs(x));
}
if (dfi[cur] == ret) {
while (stk.back() != cur) {
ndi[stk.back()] = ndidx;
stk.pop_back();
}
ndi[stk.back()] = ndidx++;
stk.pop_back();
}
return ret;
}
int indegree[100001];
int ans;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> M;
while (M--) {
int x, y; cin >> x >> y;
G[x].emplace_back(y);
}
for (int n = 1; n <= N; n++) {
if (!ndi[n]) dfs(n);
}
for (int cur = 1; cur <= N; cur++) {
for (auto& nxt : G[cur]) {
if (ndi[cur] != ndi[nxt]) indegree[ndi[nxt]]++;
}
}
for (int i = 1; i < ndidx; i++) {
if (!indegree[i]) ans++;
}
cout << ans;
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 6993 // C++] Shift Letters (0) | 2023.08.15 |
---|---|
[BOJ 18131 // C++] 치삼이의 플레이리스트 (0) | 2023.08.15 |
[BOJ 3183 // C++] Dates (0) | 2023.08.14 |
[BOJ 2435 // C++] 기상청 인턴 신현수 (0) | 2023.08.14 |
[BOJ 4593 // C++] Rock, Paper, Scissors (0) | 2023.08.14 |