티스토리 뷰
문제
https://www.acmicpc.net/problem/3648
알고리즘
2-SAT
풀이
문제에서 2-SAT의 느낌을 물씬 풍기는 문장이 몇 있습니다. '적어도 하나'라는 문장은 OR을 연상케 하고 OR은 2-CNF에서 하나의 절을 구성합니다. 그리고 한 참가자에 대해 두 가지 선택을 할 수 있다는 점도 True와 False로 연관 지을 수 있으니 2-SAT으로 문제를 접근합시다.
심사위원의 의심 없이 다음라운드를 구성할 수 있다면 하나의 참가자에 대해 모순이 되는 경우가 없다는 의미와 같습니다. 즉, 각 정점의 True와 False의 $sccid$가 일치해서는 안됩니다.
상근이가 진출하는 경우는 그래프상에서 상근이의 False 정점이 True 정점보다 위상정렬상 빠른지 확인하면 됩니다.
이전 문제에서 위상정렬상 빠른 정점을 False로 평가하는 것이 True로 평가하는 것보다 항상 이득임을 확인했습니다.
코드
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define REP(i,n) for(int i=1;i<=n;++i)
#define FAST cin.tie(NULL);cout.tie(NULL); ios::sync_with_stdio(false)
using namespace std;
#define T(x) (x<<1)
#define F(x) (x<<1|1)
int n, m, a, b, VC, SC;
vector<vector<int>> adj;
vector<int> discovered, sccid;
stack<int> st;
int scc(int here) {
int ret = discovered[here] = VC++;
st.emplace(here);
for (auto there : adj[here]) {
if (discovered[there] == -1) ret = min(ret, scc(there));
else if (sccid[there] == -1) ret = min(ret, discovered[there]);
}
if (ret == discovered[here]) {
while (1) {
int t = st.top();
st.pop();
sccid[t] = SC;
if (t == here) break;
}
SC++;
}
return ret;
}
void OR(int A, int B) {
adj[A ^ 1].emplace_back(B);
adj[B ^ 1].emplace_back(A);
}
int main() {
FAST;
while (cin >> n >> m) {
VC = SC = 0;
adj.clear();
adj.resize(n << 1);
discovered.clear();
sccid.clear();
discovered = sccid = vector<int>(n << 1, -1);
while (m--) {
cin >> a >> b;
a = a > 0 ? T(a - 1) : F(~a);
b = b > 0 ? T(b - 1) : F(~b);
OR(a, b);
}
rep(i, n << 1) if (discovered[i] == -1) scc(i);
bool flag = true;
for (int i = 0;i < n;++i) if (sccid[i] == sccid[i ^ 1]) {
flag = false;
break;
}
if (sccid[0] > sccid[1]) flag = false;
cout << (flag ? "yes" : "no") << '\n';
}
return 0;
}
'Algorithm' 카테고리의 다른 글
[백준 16915] 호텔 관리 (0) | 2020.08.14 |
---|---|
[백준 15675] 괴도 강산 (0) | 2020.08.13 |
[백준 11281] 2-SAT - 4 (0) | 2020.08.10 |
[백준 11280] 2-SAT -3 (0) | 2020.08.09 |
[백준 15483] 최소 편집 (0) | 2020.08.06 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- spring boot
- 정렬
- 이분매칭
- 펜윅트리
- sorting
- implementation
- dfs
- union find
- dijkstra
- sweeping
- 스위핑
- SCC
- Suffix Array
- 트라이
- Oracle
- 이분탐색
- kmp
- spring
- bfs
- 2-SAT
- 세그먼트트리
- Segment tree
- Fenwick
- 동적계획법
- greedy
- DP
- 좌표압축
- knapsack
- string
- hld
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함