※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 28090번 문제인 특별한 한붓그리기이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/28090
문제의 이름에는 한붓그리기가 포함되어 있지만 한붓그리기와는 관련 없는 문제이다.
주어진 이분 그래프의 최대 매칭(maximum matching) \(M\)을 하나 생각해보자. 이 때 최대 매칭의 수가 \(N\)과 같다면(즉 perfect matching이라면) 고인물이 항상 이기게 되고, 그렇지 않다면 뉴비가 항상 이기게 된다. 그 이유는 다음과 같다.
(1) 최대 매칭의 수가 \(N\)과 같다
뉴비가 어떤 노드를 고르더라도 고인물은 그 노드에 매칭되어 있는 노드를 다음 차례에 항상 고를 수 있다. 따라서 고인물이 항상 승리한다.
(2) 최대 매칭의 수가 \(N\)보다 작다
뉴비는 최대 매칭 \(M\)에 포함되지 않은 노드를 고른다. 이 때, 다음 차례에 고인물이 고르게 되는 노드는 \(M\)에 포함된 노드일 수밖에 없음을 관찰하자. 고인물이 \(M\)에 포함되지 않은 노드를 고를 수 있다면 \(M\)에 뉴비와 고인물이 각각 고른 노드쌍을 추가해 더 큰 매칭을 얻을 수 있으며, 이는 \(M\)이 최대 매칭이라는 가정에 위배되기 때문이다.
이후로 뉴비는 고인물이 고른 노드와 \(M\)에서 매칭된 노드를 골라 항상 이길 수 있다. 다음 단계에서 고인물이 고르게 되는 노드는 \(M\)에 포함된 노드일 수밖에 없음을 관찰하자. 고인물이 \(M\)에 포함되지 않은 노드를 고를 수 있다면 지금까지 뉴비와 고인물이 고른 노드를 일렬로 늘어놓고, 매칭에 포함되지 않았던 노드쌍은 매칭에 포함시키고 매칭에 포함되었던 노드쌍은 매칭에서 제외해 더 큰 매칭을 얻을 수 있으며, 이는 \(M\)이 최대 매칭이라는 가정에 위배되기 때문이다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int N, M;
vector<int> G[451];
int cnt, matching[451], visited[451];
int dfs(int cur) {
visited[cur] = 1;
for (auto &nxt:G[cur]) {
if (!matching[nxt] || (!visited[matching[nxt]] && dfs(matching[nxt]))) {
matching[nxt] = cur;
return 1;
}
}
return 0;
}
void bimatching() {
for (int i = 1; i <= N; i++) {
memset(visited, 0, sizeof(visited));
cnt += dfs(i);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> M;
while (M--) {
int x, y; cin >> x >> y;
G[x].emplace_back(y);
}
bimatching();
if (cnt == N) cout << "Oldbie";
else cout << "Newbie";
}
'BOJ' 카테고리의 다른 글
[BOJ 9910 // C++] Progress (1) | 2024.11.11 |
---|---|
[BOJ 32609 // C++] Beaking Spackwards (3) | 2024.11.08 |
[BOJ 32521 // C++] 팩트는 트리가 건강해지고 있다는 거임 (2) | 2024.11.06 |
[BOJ 32525 // C++] Duality (1) | 2024.11.05 |
[BOJ 32594 // C++] Kangaroo Race (1) | 2024.11.01 |