문제 : https://www.acmicpc.net/problem/17481
[ 문제 요약 ]
- 사람들과, 각 사람들이 좋아하는 걸그룹 멤버가 주어지면 1:1로 최대 매칭할 수 있는 횟수를 출력하는 것입니다.
- 전부 매칭이 가능한 경우, YES 출력, 아닌 경우 NO 출력 후 최대 매칭 가능한 횟수를 출력합니다.
[ 테스트 케이스 설명 ]
6 6 // 친구수 N(2<=1,000), 그룹 멤버 수 M(2<=1,000)
MIYEON // M줄에 걸쳐 멤버의 이름이 최대길이 100글자로 영어대문자로 주어짐
MINNIE
SOOJIN
SOYEON
YUQI
SHUHUA
2 YUQI SOOJIN // N줄에 걸쳐 친구 별로 좋아하는 멤버 수 K(1<=M)와 해당 그룹의 멤버 이름이 주어짐
1 SOYEON
1 YUQI
2 YUQI SHUHUA
3 MIYEON SOYEON YUQI
3 MIYEON SHUHUA SOYEON
//답, 각 매칭이 모두 가능한지 여부를 가능하면YES출력, 불가하면 NO출력 후 다음 줄에 최대한 겹치지 않게 매칭할 수 있는 최대 수를 출력
NO
5
[ 알고리즘 분류 ]
- 자료 구조
- 해시를 사용한 집합과 맵
- 이분 매칭
[ 문제 해설 ]
일반적인 이분 매칭 문제입니다. 각 사람이 좋아하는 멤버가 주어질 때, 각 멤버는 문자열이기 때문에 숫자로 변환을 위해 HashMap을 사용합니다.
그 후 일반적인 이분 매칭 알고리즘으로 문제를 풀어주면 됩니다.
이분 매칭은 두 그룹 간 가능한 최대 매칭을 찾는 알고리즘으로, 그래프 이론에서 널리 쓰이며 네트워크 연결, 작업 분배 등 실생활 문제에도 활용됩니다.
여기서 dfs 함수는, 입력되는 i가 매칭이 가능한지, 가능하지 않은지를 반환합니다. i는 사람을 의미하며, dfs 함수안에서 이미 매칭된 걸그룹 멤버가 있다면, 그 걸그룹 멤버에 매칭된 사람에게, 다른 걸그룹 멤버에게 갈 수 있는지 계속해서 묻습니다.
무한 루프를 방지하기 위해 한 dfs 함수마다 땅굴의 방문 유무를 체크하는 visit 배열을 초기화해 이용합니다.
마지막으로 문제에서 땅굴에 들어가지 못한 들쥐를 출력하라 하였으므로 총 들쥐 수에서 땅굴에 들어간 수를 빼 출력합니다.
[ 정답 코드 ]
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.StringTokenizer;
class Main{
static int N, M;
static int match[];
static boolean visit[];
static ArrayList<Integer>[] adList;
public static void main(String[] args)throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
match = new int[M + 1];
visit = new boolean[M + 1];
adList = new ArrayList[N + 1];
HashMap<String, Integer> map = new HashMap<>();
for(int i=1; i<=M; i++)
map.put(br.readLine(), i);
for(int i=1; i<=N; i++)
{
adList[i] = new ArrayList<>();
st = new StringTokenizer(br.readLine());
int k = Integer.parseInt(st.nextToken());
while(k-->0)
adList[i].add(map.get(st.nextToken()));
}
int cnt = 0;
for(int i=1; i<=N; i++)
{
Arrays.fill(visit,false);
if(dfs(i))
++cnt;
}
System.out.print(cnt == N ? "YES" : ("NO\n" + cnt));
}
static boolean dfs(int person)
{
for(int member : adList[person])
{
if(visit[member])
continue;
visit[member] = true;
if(match[member] == 0 || dfs(match[member]))
{
match[member] = person;
return true;
}
}
return false;
}
}
'알고리즘 > 이분 매칭' 카테고리의 다른 글
BOJ 백준 4376 Gopher II (2) | 2025.05.15 |
---|---|
BOJ 백준 15271 친구 팰린드롬 2 (1) | 2025.05.15 |
BOJ 백준 14433 한조 대기 중 (0) | 2025.05.14 |
BOJ 백준 2191 들쥐의 탈출 (0) | 2025.05.13 |
BOJ 백준 11376 열혈강호 2 (0) | 2025.05.11 |