문제

World Soccer Championship이 다가오고 있다! 천재적인 전술을 창조하는 플랜 아티스트 감독 도현이는 자신의 팀이 승리하도록 만반의 준비를 가하고 있다. 도현이의 전략은 경기장을 여러 개의 구역으로 나누고, 어떤 선수가 A구역에서 B구역으로 이동하게 하는 움직임을 (A, B)로 표현한다. 모든 도현이의 팀 선수들이 이 움직임만을 따라서 이동한다면 승리하리라고 도현이는 확신한다.
도현이는 선수들에게 자신의 전술을 말해주며, 다른 모든 구역에 도달할 수 있는 시작 구역을 찾은 뒤 지시한 움직임만을 따라가라고 했다. 그러나 도현이는 한 가지 간과한 것이 있었는데 그건 선수들이 자신만큼 똑똑하지 않다는 것이다. 선수들은 그러한 시작 구역을 찾는 것이 어려웠다. 이제 당신이 적절한 시작 구역을 찾아줘야 한다.
입력
첫 번째 줄에 테스트 케이스의 개수가 주어지며, 이는 11보다 작거나 같은 정수이다.
그 다음 줄부터 여러 개의 테스트 케이스가 주어지는데, 각 테스트 케이스마다 첫 번째 줄에 구역의 수 N, 지시한 움직임의 수 M이 주어지며 1 ≤ N, M ≤ 100,000 이다. 그 다음 M개의 줄에 걸쳐서 움직임 (A, B)가 주어지며, A, B는 0 ≤ A, B < N인 정수이다.
각 테스트 케이스는 하나의 빈 줄로 구분된다.
하나의 구역에서 다른 모든 구역에 도달할 수 있는지 없는지 확인을 해야합니다.
그래프의 모든 구역에 대해 dfs나 bfs를 수행해서 확인을 해도 되지만
경기장을 scc별로 분류를 하고,
위상정렬된scc들에 대해 들어오는 간선이 없는 scc가 1개인 경우에는 그 scc안에있는 정점에서 다른 모든 정점으로 이동이 가능합니다.
하지만 들어오는 간선이 없는 scc가 2개 이상인경우, 서로 이동할 수 없으므로 답이 없습니다.
타잔알고리즘으로 scc별로 분류하고, 들어오는 간선이 없는 scc의 개수를 셉니다.
#include<bits/stdc++.h>
using namespace std;
int TC, N, M, a, b, v[100001], dp[100001], s[100001], check[100001], cnt, num;
vector<int>adj[100001], st;
vector<vector<int>>scc;
int dfs(int k) {
st.push_back(k);
int parent = v[k] = ++cnt;
for (auto r : adj[k]) {
if (!v[r]) {
parent = min(parent, dfs(r));
}
else if (!s[r]) {
parent = min(parent, v[r]);
}
}
if (parent == v[k]) {
++num;
vector<int>temp;
while (1) {
auto top = st.back();
s[top] = num;
temp.push_back(top);
st.pop_back();
if (top == k)break;
}
sort(temp.begin(), temp.end());
scc.push_back(temp);
}
return parent;
}
void tarjan() {
for (int i = 0; i < N; i++)
if (!v[i])dfs(i);
}
int solve() {
for (int i = 0; i < N; i++) {
for (auto r : adj[i]) {
if (s[i] != s[r])
check[s[r]]=1;
}
}
int idx = -1;
for (int i = 1; i <= num; i++) {
if (check[i] == 0) {
if (idx == -1)idx = i;
else return -1;
}
}
return idx;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> TC;
while (TC--) {
memset(v, 0, sizeof(v));
memset(s, 0, sizeof(s));
memset(check, 0, sizeof(check));
num = 0, cnt = 0;
scc.clear();
st.clear();
cin >> N >> M;
for (int i = 0; i < N; i++) {
adj[i].clear();
}
while (M--) {
cin >> a >> b;
adj[a].push_back(b);
}
tarjan();
auto c = solve();
if (c == -1) {
cout << "Confused\n";
}
else {
for (int i = 0; i < scc[c-1].size(); i++) {
cout << scc[c-1][i] << "\n";
}
}
cout << "\n";
}
}
'baekjoon' 카테고리의 다른 글
[백준] 2573. 빙산 + 복습(다른 풀이) + C++매크로 사용 (0) | 2023.02.06 |
---|---|
[백준] 17412 도시 왕복하기 1 (0) | 2023.02.06 |
[백준] 2152 여행 계획 세우기 (0) | 2023.02.03 |
[백준] 1956 운동 (0) | 2023.02.02 |
[백준] 2056 작업 (0) | 2023.02.01 |