문제 링크
풀이
SCC를 응용한 2-SAT으로 문제를 해결할 수 있다.
2-SAT을 모른다면 BOJ 2-SAT - 3를 참고해라.
코드
#include <cstdio>
#include <vector>
#include <stack>
#include <cstring>
using namespace std;
vector<vector<int>> v, rev;
stack<int> s;
bool visited[2003];
int scc[2003], idx, n, m;
inline int T(int x) { return x << 1; }
inline int F(int x) { return x << 1 | 1; }
inline int NOT(int x) { return x ^ 1; }
void dfs(int cur) {
visited[cur] = true;
for (auto nxt : v[cur]) {
if (!visited[nxt]) dfs(nxt);
}
s.push(cur);
}
void rev_dfs(int cur) {
visited[cur] = true;
scc[cur] = idx;
for (auto nxt : rev[cur]) {
if (!visited[nxt]) rev_dfs(nxt);
}
}
void SCC() {
memset(visited, 0, sizeof visited);
for (int i = 2; i <= 2 * n + 1; i++) {
if (!visited[i]) dfs(i);
}
memset(scc, 0, sizeof scc);
memset(visited, 0, sizeof visited);
idx = 1;
while (!s.empty()) {
int cur = s.top();
s.pop();
if (!visited[cur]) {
rev_dfs(cur);
idx++;
}
}
}
int main() {
while (scanf("%d %d", &n, &m) > 0) {
v.clear(); v.resize((n << 1) + 2);
rev.clear(); rev.resize((n << 1) + 2);
while (m--) {
int a, b; scanf("%d %d", &a, &b);
a = a > 0 ? T(a) : F(-a);
b = b > 0 ? T(b) : F(-b);
v[NOT(a)].push_back(b);
v[NOT(b)].push_back(a);
rev[b].push_back(NOT(a));
rev[a].push_back(NOT(b));
}
SCC();
bool flag = false;
for (int i = 1; i <= n; i++) {
if (scc[T(i)] == scc[F(i)]) flag = true;
}
if (scc[T(1)] > scc[F(1)] && !flag) printf("yes\n");
else printf("no\n");
}
}
'Algorithm > BOJ' 카테고리의 다른 글
백준[11660] 구간 합 구하기 5 (0) | 2021.08.10 |
---|---|
백준[16991] 외판원 순회 3 (0) | 2021.08.10 |
백준[5557] 1학년 (0) | 2021.08.04 |
백준[2225] 합분해 (0) | 2021.08.04 |
백준[9084] 동전 (0) | 2021.08.04 |