백준 4305번 성격 진단 테스트
https://www.acmicpc.net/problem/4305
4305번: 성격 진단 테스트
각 테스트 케이스마다 정답을 출력한다. 한 줄에 하나의 그룹(partition)을 알파벳순으로 출력하며, 각 그룹의 알파벳순으로 가장 앞에 오는 원소 기준으로 그룹들도 알파벳순으로 출력되어야 한
www.acmicpc.net
문제
5지 선다 중에 1개를 선택하는 성격 진단 테스트 입니다.
A B C D E 중에 A를 선택하면,
A가 B, C, D, E 보다 더 선호하는 보기라는 것입니다.
이렇게 여러 문항을 테스트 하다가 모순이 생길 수 있습니다.
모순이 있는 집단을 찾는 문제입니다.
풀이
모순이 생긴다는 의미는
A 보다 B를 선호한다고 골랐는데, 다른 문항에서 B 보다 A를 선호한다고 고른 것입니다.
(A > B && B > A)
이러한 부등호를 방향이 있는 간선으로 표시하면
A -> B && B -> A 가 됩니다.
이는 A와 B가 사이클을 이루게 됩니다.
즉, 그래프에서 사이클을 찾는 문제가 됩니다.

예제를 그래프로 그리면 아래와 같습니다.
간선이 많아서 보기 힘들지만, 여기서 사이클은 하나 밖에 존재하지 않습니다.

I, J, K 는 하나의 사이클로 판단해 한 줄로 출력하면 됩니다.
이 외의 나머지는 자기 자신으로만 구성된 사이클 이므로 한 줄에 하나씩만 출력해주면 됩니다.
사이클을 찾는 문제는 SCC 알고리즘으로 풀 수 있습니다.
https://kdr06006.tistory.com/6
강한 연결 요소 (Strongly Connected Component)
안녕하세요. 오늘은 줄여서 SCC 라고도 불리는 강한 연결 요소에 대해 알아보도록 하겠습니다. 사이클 유향 그래프에서 사이클을 찾는 알고리즘을 SCC 알고리즘 이라고 합니다. 하나의 SCC에 속하
kdr06006.tistory.com
코드
#include <cstdio>
#include <algorithm>
#include <stack>
#include <vector>
using namespace std;
bool check[26];
vector<int> adj[26];
struct SCC {
int dfsn[26], dfsNumber;
int sccn[26], sccNumber;
bool finish[26];
stack<int> S;
void init() {
dfsNumber = sccNumber = 0;
for (int i = 0; i < 26; ++i) {
finish[i] = false;
dfsn[i] = sccn[i] = 0;
}
}
int dfs(int cur) {
int ret = dfsn[cur] = ++dfsNumber;
S.push(cur);
for (auto n : adj[cur]) {
if (!dfsn[n]) ret = min(ret, dfs(n));
else if (!finish[n]) ret = min(ret, dfsn[n]);
}
if (ret == dfsn[cur]) {
++sccNumber;
while (!S.empty()) {
int t = S.top(); S.pop();
sccn[t] = sccNumber;
finish[t] = true;
if (t == cur) break;
}
}
return ret;
}
void solve() {
for (int i = 0; i < 26; ++i) {
if (check[i] && !dfsn[i])
dfs(i);
}
for (int i = 0; i < 26; ++i) {
if (!sccn[i]) continue;
printf("%c ", i + 'A');
for (int j = i + 1; j < 26; ++j) {
if (sccn[i] == sccn[j]) {
printf("%c ", j + 'A');
sccn[j] = 0;
}
}
printf("\n");
sccn[i] = 0;
}
}
}scc;
void init() {
for (int i = 0; i < 26; ++i) {
check[i] = false;
adj[i].clear();
}
scc.init();
}
void put_edge(char c1, char c2) {
adj[c1 - 'A'].push_back(c2 - 'A');
}
int main()
{
//freopen("input.txt", "r", stdin);
while (true) {
int n;
scanf("%d", &n);
if (n == 0) break;
init();
char arr[6];
while (n--) {
for (int i = 0; i < 6; ++i) {
scanf(" %c", &arr[i]);
check[arr[i] - 'A'] = true;
}
for (int i = 0; i < 5; ++i) put_edge(arr[5], arr[i]);
}
scc.solve();
printf("\n");
}
}
감사합니다.
'BOJ' 카테고리의 다른 글
[BOJ 18251] 내 생각에 A번인 단순 dfs 문제가 이 대회에서 E번이 되어버린 건에 관하여 (Easy) (0) | 2023.08.24 |
---|---|
[BOJ 3392] 화성 지도 (0) | 2023.08.21 |
[BOJ 13711] LCS 4 (0) | 2023.08.02 |
[BOJ 20942] 신촌지역 초중고등학생 프로그래밍 대회 동아리 연합 대회 (0) | 2023.07.27 |
[BOJ 3648] 아이돌 (0) | 2023.07.26 |