알고리즘/문제풀이
[백준 22742번] Make Friendships
Ohnim · 오님
2024. 9. 3. 01:34
문제 링크
https://www.acmicpc.net/problem/22742
문제 요약
이팍이는 파티에서 여러 여자친구를 새롭게 사귀었고, 이들과 데이트 일정을 잡으려고 한다. 이삭이는 한 번에 한 명의 여자친구만 만날 수 있으며, 만날 수 있는 시간은 정해져 있다. 또한 각 여자친구마다 이삭이를 만날 수 있는 시간이 정해져 있다. 이 때 이삭이가 최적의 일정으로 스케줄링을 했을 때 최대한 만날 수 있는 여자친구들의 수를 구하는 문제이다.
문제 풀이
이삭이가 사용할 수 있는 시간들을 왼쪽 노드로, 각 여자친구들을 오른쪽 노드로 설정하면 문제를 이분 그래프로 모델링 할 수 있다. 아래 그림은 예제 입력을 이분 그래프로 모델링 한 결과이다.
이제 문제는 이분 그래프에서 최대 매칭을 구하는 문제로 바뀌었고, 이분 매칭 알고리즘을 이용해 문제를 풀 수 있다.
그래프를 구현할 때에는 이삭이가 가능한 시간들에 Map과 같은 자료구조를 이용해서 인덱스를 기록해 놓는다. 그런 다음 여자친구들이 이삭이를 만날 수 있는 시간들이 Map에 있는지 확인을 한 뒤, 해당 시간이 Map에 존재하면 간선을 연결하여 이분 그래프를 구성한다.
소스 코드
더보기
#include <stdio.h>
#include <vector>
#include <map>
using namespace std;
vector<int> matched;
vector<bool> visited;
vector<vector<int>> node;
// n: 왼쪽 노드의 수
void init(int n) {
matched.assign(n, -1);;
visited.assign(n, false);
node.assign(n, vector<int>());
}
// DFS를 이용해 최대 매칭을 찾는 함수
bool dfs(int here) {
if (visited[here]) {
return false;
}
visited[here] = true;
for (int there: node[here]) {
if (matched[there] == -1 || dfs(matched[there])) {
matched[there] = here;
return true;
}
}
return false;
}
int main() {
int m;
// 오른쪽 노드의 수를 입력 받음(이삭이가 사귄 여자친구들의 수)
while (scanf("%d", &m) && m) {
int n, t, x;
// 시간과 왼쪽 노드 인덱스를 매핑하는 해시맵
map<int, int> hash;
// 왼쪽 노드의 수를 입력 받음(이삭이가 가능한 시간)
scanf("%d", &n);
for (int i = 0 ; i < n ; ++i) {
scanf("%d", &x);
hash[x] = i;
}
init(n);
for (int i = 0 ; i < m ; ++i) {
scanf("%d", &t);
while (t--) {
scanf("%d", &x);
// 입력된 시간이 해시맵에 존재하면
if (hash.count(x)) {
// 왼쪽 노드에 오른쪽 노드 번호를 연결
node[hash[x]].push_back(i);
}
}
}
int ans = 0;
for (int i = 0 ; i < n ; ++i) {
visited.assign(n, false);
if (dfs(i)) {
++ans;
}
}
printf("%d\n", ans);
}
}