백준 13344번 Chess Tournament
문제
Your friend is an organizer of the International Chess Playing Championship. He is worried that some of the contestants may be cheating, and he has asked you to help out. The chess players are allowed to report matches to the jury themselves, and this is not checked with the reported opponent. So, it is possible for competitors to make up matches and falsely report themselves as the winners.
Since chess is a game of skill, and not of chance, a player will always beat their opponent if their skill level is higher. A game will result in a draw if and only if the two players’ skills are exactly equal.
However, the skill level of the players is not known. He has therefore asked you to write a program that, given a list of reported matches, determines whether this list is consistent or not. The list is inconsistent if we can determine that at least reported match is falsely reported, otherwise it is consistent.
문제풀이
(0) 생각
(1) 코드 29~35
(2) 코드 36~49
(3) 코드 50~63
(4) 코드 64~67
#include<bits/stdc++.h> | |
using namespace std; | |
typedef pair<int, int> pii; | |
const int MAX = 50005; | |
int N, M; | |
// adj[x] : x를 root로하는 컴포넌트보다 큰 컴포넌트(의 root노드) 저장 | |
set<int> adj[MAX]; | |
// union-find | |
int R[MAX]; | |
int find(int x) { | |
if (R[x] < 0) return x; | |
return R[x] = find(R[x]); | |
} | |
void merge(int x, int y) { | |
int xRoot = find(x); | |
int yRoot = find(y); | |
if (xRoot != yRoot) R[xRoot] = yRoot; | |
} | |
set<int> arr; // 각 컴포넌트의 root 노드 저장 | |
int indegree[MAX]; // 각 컴포넌트에 들어오는 엣지 수 | |
int main() {ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); | |
memset(R, -1, sizeof(R)); // 초기화 | |
cin >> N >> M; | |
vector<pii> V; // 일단 관계 저장 | |
for (int i = 0; i < M; ++i) { | |
int a, b; | |
char c; | |
cin >> a >> c >> b; | |
if (c == '=') merge(a, b); // 하나의 컴포넌트로 묶기 | |
else V.push_back(pii(a, b)); // a > b | |
} | |
for (auto it : V) {// 관계를 컴포넌트별로 생각 | |
int a = it.first; | |
int b = it.second; | |
a = find(a); // 컴포넌트 별로 생각한다. | |
b = find(b); | |
// 컴포넌트 의 root들 저장 | |
arr.insert(a); | |
arr.insert(b); | |
// 컴포넌트 끼리 연결관계 최신화 | |
if (!adj[b].count(a)) { // 컴포넌트끼리 간선은 1개 ( 중복제거 ) | |
indegree[a]++; // a보다 능력 낮은 컴포넌트 수 ++ | |
adj[b].insert(a); | |
} | |
} | |
// 위상정렬 | |
queue<int> Q; | |
for (int it : arr) | |
if (indegree[it] == 0) Q.push(it); // 능력 제일 낮은거로 시작 | |
int cnt = 0; // 정렬 된 컴포넌트의 수 | |
while (!Q.empty()) { | |
int curr = Q.front(); | |
Q.pop(); | |
cnt++; | |
for (auto it : adj[curr]) { | |
indegree[it]--; | |
if (indegree[it] == 0) Q.push(it); | |
} | |
} | |
// 모든 컴포넌트의 위상이 맞는 경우 ( 모든 컴포넌트 개수만큼 cnt 가 세어진 경우 ) | |
if (cnt == arr.size()) cout << "consistent" << '\n'; | |
// 탈출 못한 컴포넌트 있는 경우 | |
else cout << "inconsistent" << '\n'; | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!