※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 3747번 문제인 완벽한 선거!이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/3747
3747번: 완벽한 선거!
어떤 나라에서는 (뭔 나라인지는 기억이 안 나지만), 후보 {1, 2 ... N}이 나와서 국회의원 선거를 치루고 있다. 여론조사에서는 사람들마다 "만약 두 후보 i, j에 대해서, 그 두 후보의 선거 결과가
www.acmicpc.net
주어진 2-CNF들을 모두 만족시키는 선거 결과가 존재하는지를 계산하는 2-SAT 문제이다. 이 문제는 사람 수 N, 2-CNF의 수를 M이라고 할 때 SCC를 이용한 O(N+M) 해법이 잘 알려져있다.
글쓴이는 i번 후보가 당선된다는 것을 나타내는 노드를 i번 노드, 떨어진다는 것을 나타내는 노드를 2N+1-i번 노드로 계산하였다. 이 상태로 SCC를 구해 i번 노드와 2N+1-i번 노드가 같은 컴포넌트에 있는 경우가 있다면 0, 아니면 1을 출력해주었다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int N, NN, M;
vector<int> G[2001];
int dfi[2001], dfidx = 1;
int sci[2001], scidx = 1;
vector<int> stk;
int dfs(int current) {
stk.emplace_back(current);
int ret = dfi[current] = dfidx++;
for (auto node : G[current]) {
if (sci[node]) continue;
if (dfi[node]) ret = min(ret, dfi[node]);
else ret = min(ret, dfs(node));
}
if (ret == dfi[current]) {
while (stk.back() != current) {
sci[stk.back()] = scidx;
stk.pop_back();
}
sci[current] = scidx++;
stk.pop_back();
}
return ret;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
while (cin >> N >> M) {
NN = N * 2 + 1;
for (int i = 1; i < NN; i++) G[i].clear();
memset(dfi, 0, sizeof(dfi));
memset(sci, 0, sizeof(sci));
dfidx = scidx = 1;
while (M--) {
int x, y; cin >> x >> y;
if (x < 0) x += NN;
if (y < 0) y += NN;
G[NN - x].emplace_back(y);
G[NN - y].emplace_back(x);
}
for (int i = 1; i < NN; i++) {
if (sci[i]) continue;
dfs(i);
}
int ans = 1;
for (int i = 1; i <= N; i++) {
if (sci[i] == sci[NN - i]) ans = 0;
}
cout << ans << '\n';
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 10976 // C++] 피난 (0) | 2022.01.01 |
---|---|
[BOJ 1739 // C++] 도로 정비하기 (0) | 2021.12.31 |
[BOJ 23237 // C++] How Many Subtrees? (0) | 2021.12.29 |
[BOJ 1648 // C++] 격자판 채우기 (0) | 2021.12.28 |
[BOJ 19941 // C++] 햄버거 분배 (0) | 2021.12.27 |