※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 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

+ Recent posts