문제 : https://www.acmicpc.net/problem/30976

 

[ 문제 요약 ]

  • 남, 여의 키가 주어지고, 각 남자와 여자가 선호하는 키의 기준이 주어집니다.
  • 여자는 자신의 선호 기준 보다 작은 키의 남자만 연결을 하고, 남자는 자신의 선호 기준 보다 큰 키의 여자만 원합니다. 이때 1 : 1 매칭 가능한 남녀 그룹의 수를 출력합니다.

 

[ 테스트 케이스 설명 ]

 

2 2		// 여학생수(1<=400, 남학생수(1<=400)
168 164	// i번째 여학생의 키
179 183	// i번째 남학생의 키
180 190	// i번째 여학생의 선호기준 ( 여학생은 자신의 선호 기준보다 작은 학생만 )
155 165	// i번째 남학생의 선호기준 ( 남학생은 자신의 선호 기준보다 키가 큰 학생만 )
 답 : 1

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

 

이 문제는 인접 리스트만 잘 생성해 주면 일반적인 이분 매칭 문제와 똑같이 풀 수 있습니다.

 

남 → 여로 갈 수 있도록 인접 리스트를 생성하되, 남자가 선호하는 여자라 하더라도 여자가 그 남자를 선호하지 않으면 인접 리스트를 생성하지 않게 합니다.

 

이렇게 리스트만 잘 생성하면 일반 이분 매칭 알고리즘으로 간단히 풀 수 있습니다.

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

class Main{
	
	static int match[];
	static boolean visit[];
	static List<Integer> adList[];
	
	public static void main(String[] args)throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int N = Integer.parseInt(st.nextToken());// 여학생수(1<=400)
		int M = Integer.parseInt(st.nextToken());// 남학생수(1<=400)
		int G[] = new int[N + 1];// 여학생의 키
		int B[] = new int[M + 1];// 남학생의 키
		int T[] = new int[N + 1];// 여학생의 선호 기준
		
		match = new int[N + 1];
		visit = new boolean[N + 1];
		adList = new ArrayList[M + 1];
		// 리스트 초기화
		for(int i=1; i<=M; i++)
			adList[i] = new ArrayList<>();
		
		// 여학생의 키 입력
		st = new StringTokenizer(br.readLine());
		for(int i=1; i<=N; i++)
			G[i] = Integer.parseInt(st.nextToken());
		
		// 남학생의 키 입력
		st = new StringTokenizer(br.readLine());
		for(int i=1; i<=M; i++)
			B[i] = Integer.parseInt(st.nextToken());
		
		// 여학생의 선호 기준 입력
		st = new StringTokenizer(br.readLine());
		for(int i=1; i<=N; i++)
			T[i] = Integer.parseInt(st.nextToken());
		
		// 남학생의 선호 기준을 입력 받으면서 인접 리스트 생성
		st = new StringTokenizer(br.readLine());
		for(int i=1; i<=M; i++)
		{
			int h = Integer.parseInt(st.nextToken());// 남학생의 선호기준
			for(int j=1; j<=N; j++)// 모든 여학생 순회
				if(h < G[j] && T[j] > B[i])
					adList[i].add(j);
		}
		
		int cnt = 0;
		
		for(int i=1; i<=M; i++)
		{
			Arrays.fill(visit, false);
			if(dfs(i))
				++cnt;
		}
		
		System.out.print(cnt);
	}
	public static boolean dfs(int boy) {
		for(int girl : adList[boy])
		{
			if(visit[girl])
				continue;
			
			visit[girl] = true;
			
			if(match[girl] == 0 || dfs(match[girl]))
			{
				match[girl] = boy;
				return true;
			}
		}
		return false;
	}
}

 

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 11377 열혈강호 3  (0) 2025.05.16
BOJ 백준 4376 Gopher II  (2) 2025.05.15
BOJ 백준 15271 친구 팰린드롬 2  (1) 2025.05.15
BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 14433 한조 대기 중  (0) 2025.05.14

 

문제 : https://www.acmicpc.net/problem/11377

 

[ 문제 요약 ]

  • 직원 N 명, 일 M 개가 주어지며, K 명의 직원은 일을 최대 2개, 나머진 1개의 일만 담당 가능할 때, 처리할 수 있는 일의 최대 수를 출력합니다.

 

[ 테스트 케이스 설명 ]

5 5 1	// 직원수(1<1,000), 일수(1<=1,000), 일2개할 수 있는 직원(1<=N)
3 1 2 3	// i번 직원이 할 수 있는 일의 개수와 그만큼 일이 주어짐
3 1 2 3
1 5
1 5
1 5
답 : 4

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

 

이 문제는 아래 문제와 비슷합니다.

 

https://kyjdummy.tistory.com/54 [ 열혈강호 2 ]

 

BOJ 백준 11376 열혈강호 2

문제 : https://www.acmicpc.net/problem/2188 [ 문제 요약 ]일과 사람이 주어지면, 사람과 일을 매칭 시킬 수 있는 최대 수를 출력합니다. 단, 한 사람은 최대 2개의 일을 받아 할 수 있습니다. [ 테스트 케이

kyjdummy.tistory.com

 

dfs 함수를 짤 때, 함수의 파라미터로 사람을 넣으면, 그 사람이 job에 매칭됐을 때 true, 안되면 false가 나오는 함수를 짭니다. 이 내용은 다른 여러 일반 이분 매칭 문제와 똑같습니다.

 

중요한 건 K명이 2개의 일을 할 수 있기 때문에 이를 구현하기 위해 먼저, 사람과 일에 대해 1 : 1로 매칭이 되도록 계산을 한 후,

 

다시 1번 사람부터 N 번 사람까지 탐색하면서 K 번 매칭이 될 때까지 dfs 함수를 돌려줍니다.

 

이게 가능한 이유는 dfs 함수 작동 방식에 있습니다.

 

dfs 함수는 job에 사람이 매칭 되면, true or false를 반환합니다. 중요한 건 사람이 누구든 상관하지 않는다는 것입니다.

 

같은 사람이 계속 들어오던지, 아니던지 상관하지 않고 job에 매칭만 되면 true, 안되면 false가 반환됩니다.

 

그리고 특정 job에 사람이 매칭되어 있다면, 그 job에 매칭된 사람한테도 다른 job으로 이동 가능한지 연쇄적으로 계속 묻기 때문에 완벽하게 처음 입력된 사람이 job에 매칭 가능한지 탐색 가능합니다.

 

그래서 별도로 모든 사람에대해 K번만 한번더 돌려주면 됩니다.

 

그리고 알고리즘의 실행 속도를 높이기 위해, 이미 구한 매칭 가능한 job의 수가 총 job의 수와 같다면 조기 종료해 줍니다. 이를 통해 알고리즘 속도를 개선할 수 있습니다.

 

또한, 보통 dfs 함수를 진행하기 전에 무한 루프를 방지하고자 visit 배열을 신규로 생성하거나, false로 초기화하는데, 이렇게 하는 것보다, visit 배열을 int로 선언하고 각 dfs 순회마다 time이라는 변수를 두어 그 전역변수의 숫자와 visit 배열의 저장된 값이 같다면 방문한 것으로 판단하는 것이 효율적입니다.

 

 

[ boolean으로 dfs 함수마다 초기화했을 때 속도 ]

 

 

[ int배열로 선언했을 때 속도 ]

 

 

[ int배열로 방문 체크 + 매칭 횟수와 총 일의 개수가 같을 때 조기종료 할 경우 속도 ]

 

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

class Main{
	
	static int time;
	static int match[];
	static int visitTime[];
	static ArrayList<Integer> adList[];
	static int N, M, K;
	
	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());// 직원수(1<1,000)
		M = Integer.parseInt(st.nextToken());// 일수(1<=1,000)
		K = Integer.parseInt(st.nextToken());// 일2개할 수 있는 직원(1<=N)
		
		match = new int[M + 1];
		visitTime = new int[M + 1];
		adList = new ArrayList[N + 1];
		
		for(int person=1; person<=N; person++)
		{
			adList[person] = new ArrayList<>();
			st = new StringTokenizer(br.readLine());
			int j = Integer.parseInt(st.nextToken());
			while(j-->0)
			{
				int job = Integer.parseInt(st.nextToken());
				adList[person].add(job);
			}
		}
		
		int cnt = 0;
		
		for(int person=1; person<=N && cnt != M; person++)
		{
			++time;
			if(dfs(person))
				++cnt;
		}
		
		for(int person=1; person<=N && K != 0 && cnt != M; person++)
		{
			++time;
			if(dfs(person))
			{
				++cnt;
				--K;
			}
		}
		
		System.out.print(cnt);
	}
	// dfs 함수는 job에 사람이 매칭될 때마다 true를 반환. person이 갖고있는 일에 대해 매칭이 어쨋든 가능하면 무조건 true반환
	// 내가 갖고있는 job을 내가 할 수 있는지 확인하기 위해, 내가 할 수 있는 job에 사람이 매칭되어있다면,
	// 그 사람에게 다른 job으로 갈 수 있는지 연쇄적으로 계속 묻는다.
	static boolean dfs(int person)
	{
		for(int job : adList[person])
		{
			if(visitTime[job] == time)
				continue;
			
			visitTime[job] = time;
			
			if(match[job] == 0 || dfs(match[job]))
			{
				match[job] = person;
				return true;
			}
		}
		return false;
	}
}

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 30976 사랑의 큐피드  (1) 2025.05.17
BOJ 백준 4376 Gopher II  (2) 2025.05.15
BOJ 백준 15271 친구 팰린드롬 2  (1) 2025.05.15
BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 14433 한조 대기 중  (0) 2025.05.14

 

문제 : https://www.acmicpc.net/problem/4376

 

[ 문제 요약 ]

  • 동물 수, 구덩이 수, 매 도착시간(초 단위), 동물의 속도(m/s)가 주어지고, 동물의 좌표와 구덩이의 좌표가 주어집니다.
  • 구덩이에 동물 하나만 들어갈 수 있을 때 구덩이에 들어가지 못하는 동물의 수를 출력합니다.

 

[ 테스트 케이스 설명 ]

2 2 5 10		// 동물 수, 구멍수, 매 도착시간(초단위), 동물의 속도(초당 미터 단위)
1.0 1.0			// N줄에 동물의 좌표가 주어짐(미터 단위)
2.0 2.0
100.0 100.0		// M줄에 구멍의 좌표가 주어짐(미터 단위)
20.0 20.0
못들어간 동물 수 : 1

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

 

매의 도착시간을 이용해 동물이 최대로 갈 수 있는 거리를 구하고, 해당 거리 내에 있는 구덩이의 좌표들을 인접 리스트로 만들어 이분 매칭으로 답을 구할 수 있습니다.

 

이때 피타고라스 정리를 이용해 간단하게 인접 리스트에 넣을 정보를 구할 수 있습니다. 아래 문제와 거의 비슷합니다.

 

https://kyjdummy.tistory.com/56

 

BOJ 백준 2191 들쥐의 탈출

문제 : https://www.acmicpc.net/problem/2191 [ 문제 요약 ]들쥐의 위치와 땅굴의 위치가 소수점 셋째 자리까지 주어지며, 들쥐의 초당 이동 거리와 매의 도착 시간이 주어집니다.매가 도착할 때 땅굴에 들

kyjdummy.tistory.com

 

차이점은, 이 문제는 테스트 케이스가 여러 개이기 때문에 빈 값이 입력될 때까지 무한 루프를 돌려주어야 합니다.

 

디테일은 코드를 통해 확인 가능합니다.

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

class Main{
	
	static int N, M, S, V;
	static double dist;
	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));
		StringBuilder sb = new StringBuilder();
		while(true)
		{
			String str = br.readLine();
			if(str == null || "".equals(str))
				break;
			
			StringTokenizer st = new StringTokenizer(str);
			N = Integer.parseInt(st.nextToken());// 동물 수(1<=100)
			M = Integer.parseInt(st.nextToken());// 구멍수(1<=100)
			S = Integer.parseInt(st.nextToken());// 매 도착시간(초단위)(1<=100)
			V = Integer.parseInt(st.nextToken());// 동물의 속도(초당 미터 단위) (1<=100)
			dist = S * V * S * V;
			match = new int[M + 1];
			visit = new boolean[M + 1];
			adList = new ArrayList[N + 1];
			double pos[][] = new double[N + 1][2];
			
			for(int i=1; i<=N; i++)
			{
				st = new StringTokenizer(br.readLine());
				pos[i][0] = Double.parseDouble(st.nextToken());
				pos[i][1] = Double.parseDouble(st.nextToken());
				adList[i] = new ArrayList<>();
			}
			
			for(int i=1; i<=M; i++)
			{
				st = new StringTokenizer(br.readLine());
				double x = Double.parseDouble(st.nextToken());
				double y = Double.parseDouble(st.nextToken());
				
				for(int j=1; j<=N; j++)
				{
					double diffX = x - pos[j][0];
					double diffY = y - pos[j][1];
					if(dist >= diffX * diffX + diffY * diffY)
						adList[j].add(i);
				}
			}
			
			int cnt = N;
			
			for(int i=1; i<=N; i++)
			{
				Arrays.fill(visit, false);
				if(dfs(i))
					--cnt;
			}
			sb.append(cnt).append('\n');
		}
		System.out.print(sb);
	}
	static boolean dfs(int animal) {
		
		for(int hole : adList[animal])
		{
			if(visit[hole])
				continue;
			
			visit[hole] = true;
			
			if(match[hole] == 0 || dfs(match[hole]))
			{
				match[hole] = animal;
				return true;
			}
		}
		
		return false;
	}
}

문제 : https://www.acmicpc.net/problem/15271

 

[ 문제 요약 ]

  • 주어진 그래프에서 **출석 번호가 짝수인 사람(남자)**과 **홀수인 사람(여자)**만 서로 연결될 수 있습니다. 이때 최대한 많은 남녀 쌍을 매칭하고, 매칭되지 않은 사람의 수를 최소화하는 것이 목표입니다.

 

[ 테스트 케이스 설명 ]

3 3	// 사람수(2<=200), 관계도 수(0<=(N^2 - N)/2)
1 2	// 친한 친구 관계가 주어짐
2 3
3 1
답 : 3

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

 

문제 설명에서 남, 여만 짝이 가능하다 하였으므로, 남,녀일 때, 남자 → 여자로 갈 수 있게 만들어 줍니다.

 

그리고 모든 사람에 대해서 탐색합니다. 이때 모든 사람에 대해 탐색해도, 여자는 남자로 갈 수 없으므로 자연히 남자만 탐색되게 되므로 모든 남녀 매칭을 해줄 수 있습니다.

 

한 번의 dfs에서 남,여로 두 명의 사람을 매칭하기 때문에 매칭된 사람의 수를 더할 때 2씩 증가시켜 줍니다.

 

무한 루프를 방지하기 위해 dfs 함수안에서 방문하지 않은 여자만 탐색하도록 합니다.

 

정답 출력 시 구한 cnt에 +1을 해주어야 합니다. 모두 매칭되지 않은 경우 한 명은 주최자로 추가하여 무대에 오르는 사람의 수를 최대로 합니다.

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
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());// 사람수(2<=200)
		M = Integer.parseInt(st.nextToken());// 관계도 수(0<=(N^2 - N)/2)
		match = new int[N + 1];
		visit = new boolean[N + 1];
		adList = new ArrayList[N + 1];
		
		for(int i=0; i<=N; i++)
			adList[i] = new ArrayList<>();
		
		for(int i=0; i<M; i++)
		{
			st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());
			if(a % 2 != b % 2)
			{
				if(a % 2 == 0) // 남 -> 여로 갈 수 있게 세팅
					adList[a].add(b);
				else
					adList[b].add(a);
			}
		}
	
		int cnt = 0;
		
		for(int i=1; i<=N; i++)
		{
			Arrays.fill(visit, false);
			if(dfs(i))
				cnt += 2;
		}
		
		System.out.print(Math.min(cnt + 1, N));
	}
	static boolean dfs(int boy) {
		
		for(int girl : adList[boy])
		{
			if(visit[girl])
				continue;
			
			visit[girl] = true;
			
			if(match[girl] == 0 || dfs(match[girl]))
			{
				match[girl] = boy;
				return true;
			}
		}
		
		return false;
	}
}

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 11377 열혈강호 3  (0) 2025.05.16
BOJ 백준 4376 Gopher II  (2) 2025.05.15
BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 14433 한조 대기 중  (0) 2025.05.14
BOJ 백준 2191 들쥐의 탈출  (0) 2025.05.13

 

문제 : 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

 

문제 : https://www.acmicpc.net/problem/14433

 

[ 문제 요약 ]

  • 사람과 원하는 영웅이 주어집니다. 팀이 2팀이기 때문에 각 팀당 이분 매칭 최대 매칭 수를 구해서 최대로 매칭된 수가 첫 번째 팀이 작다면 이기는 것, 같거나 크다면 진 겁니다.

 

[ 테스트 케이스 설명 ]

5 4 5 3	// 사람수N(1<=300), 영웅수M(1<=300), 각 팀의 팀원들이 원하는 영웅 수 k1, k2(1<=500) 
1 1	// k1개의 줄에걸쳐 두수 i(1<=N),j(1<=M)가 주어짐, i번 플레이어가 j번을 고르고 싶어한다는 것
2 2
3 3
4 4
5 2
1 1	// k2줄에 걸쳐 같은 형식으로 주어짐
2 1
3 1
//승급할 수 있으면 ‘네 다음 힐딱이’를, 승급할 수 없으면 ‘그만 알아보자’를 출력한다.
//답 : 그만 알아보자

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

  • 일반적인 이분 매칭 문제로, 팀이 2개이기 때문에 두 번 이분 매칭을 돌려주면 됩니다.
  • 코드를 간단하게 하기 위해 반복문 안에서 두 번 팀을 순회하며 이분 매칭하도록 구현했습니다.

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
class Main{
	
	static final String WIN = "네 다음 힐딱이";
	static final String LOSE = "그만 알아보자";
	
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer st;
	
	static int N, M;
	static int match[];
	static boolean visit[];
	static ArrayList<Integer> adList[];
	
	public static void main(String[] args)throws Exception{
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());// 사람수N(1<=300)
		M = Integer.parseInt(st.nextToken());// 영웅수M(1<=300)
		// 각 팀의 팀원들이 원하는 영웅 수 k1, k2(1<=500)
		int K1 = Integer.parseInt(st.nextToken());
		int K2 = Integer.parseInt(st.nextToken());

		System.out.print(getMaxMatch(K1) < getMaxMatch(K2) ? WIN : LOSE);
	}
	static int getMaxMatch(int K)throws Exception {
		match = new int[M + 1];
		visit = new boolean[M + 1];
		adList = new ArrayList[N + 1];
		
		for(int j=1; j<=N; j++)
			adList[j] = new ArrayList<>();
		
		while(K-->0)
		{
			st = new StringTokenizer(br.readLine());
			int user = Integer.parseInt(st.nextToken());
			int hero = Integer.parseInt(st.nextToken());
			adList[user].add(hero);
		}
		
		int cnt = 0;
		
		for(int user=1; user<=N; user++)
		{
			Arrays.fill(visit, false);
			if(dfs(user))
				cnt++;
		}
		
		return cnt;
	}
	static boolean dfs(int user) {
		for(int hero : adList[user])
		{
			if(visit[hero])
				continue;
			
			visit[hero] = true;
			
			if(match[hero] == 0 || dfs(match[hero]))
			{
				match[hero] = user;
				return true;
			}
		}
		return false;
	}
}

 

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 15271 친구 팰린드롬 2  (1) 2025.05.15
BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 2191 들쥐의 탈출  (0) 2025.05.13
BOJ 백준 11376 열혈강호 2  (0) 2025.05.11
BOJ 백준 2188 축사 배정  (0) 2025.05.11

 

문제 : https://www.acmicpc.net/problem/2191

 

[ 문제 요약 ]

  • 들쥐의 위치와 땅굴의 위치가 소수점 셋째 자리까지 주어지며, 들쥐의 초당 이동 거리와 매의 도착 시간이 주어집니다.
  • 매가 도착할 때 땅굴에 들어가지 못한 들쥐의 수를 출력합니다. 단, 매가 도착한 시간과 들쥐가 땅굴에 들어간 시간이 같으면 들어간 것으로 합니다.

 

[ 테스트 케이스 설명 ]

2 2 5 10	// 들쥐수(1≤100), 땅굴수(1≤100), 매 도착시간(1≤100), 들쥐의 초당 이동 거리(1≤100)
1.0 1.0		// N개의 줄에 들쥐 좌표 x,y가 주어짐(절대 값1,000이하 소수점세자리 주어짐)
2.0 2.0
100.0 100.0	// M개 줄에 땅굴의 좌표 x,y가 주어짐(절대 값1,000이하 소수점세자리 주어짐)
20.0 20.0
잡아먹히는 들쥐 최솟값 : 1

 

 

[ 알고리즘 분류 ]

  • 기하학
  • 이분 매칭

 

[ 문제 해설 ]

 

매가 올 때까지 들쥐가 이동 가능한 최대 거리는 [매 도착시간 * 들쥐 초당 이동거리]입니다.

 

들쥐와 땅굴 사이의 거리는 피타고라스 정리를 이용해 √((x1 - x2) ² + (y1 - y2) ²)로 계산합니다. 이 거리가 [매 도착 시간 × 들쥐 초당 이동 거리] 이하일 경우, 해당 들쥐는 땅굴에 도달할 수 있다고 판단합니다

 

주어진 값이 소수점 세 자리까지 주어지기 때문에, 소수점 오류를 방지하고자 OFF_SET을 1000으로 두고 곱해주어, int로 바꿔 연산합니다.

 

이렇게 하는 이유는, 소수점 오차로 인해 잘못된 비교 결과가 나올 수 있으므로, 모든 좌표에 1000을 곱하여 정수 형태로 바꾼 후 계산합니다. 예를 들어, 1.001과 1.002는 실수로 비교 시 부정확할 수 있으므로 각각 1001, 1002로 바꾸면 오차 없이 정확하게 비교할 수 있습니다.

 

만약 들쥐가 땅굴에 갈 수 있다면 인접 리스트에 담아줍니다. 인접 리스트는 들쥐가 index가 되고, 그 안에 저장되는 값들이 갈 수 있는 땅굴입니다.

 

그 후 일반적인 이분 매칭 알고리즘으로 문제를 풀어주면 됩니다.

 

이분 매칭은 두 그룹 간 가능한 최대 매칭을 찾는 알고리즘으로, 그래프 이론에서 널리 쓰이며 네트워크 연결, 작업 분배 등 실생활 문제에도 활용됩니다.

 

여기서 dfs 함수는, 들쥐 i가 땅굴에 들어갈 수 있느냐를 TRUE, FALSE를 반환하는 함수입니다. dfs 함수안에서 이미 매칭된 땅굴이 있다면, 그 땅굴에 매칭된 들쥐에게 다른 땅굴로 갈 수 있는지 계속해서 묻습니다.

 

무한 루프를 방지하기 위해 한 dfs 함수마다 땅굴의 방문 유무를 체크하는 visit 배열을 초기화해 이용합니다.

 

마지막으로 문제에서 땅굴에 들어가지 못한 들쥐를 출력하라 하였으므로 총 들쥐 수에서 땅굴에 들어간 수를 빼 출력합니다.

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

class Main{
	
	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());
		final int OFF_SET = 1_000;
		int N = Integer.parseInt(st.nextToken());// 들쥐수(1≤100)
		int M = Integer.parseInt(st.nextToken());// 땅굴수(1≤100)
		int S = Integer.parseInt(st.nextToken());// 매 도착시간(1≤100)
		int V = Integer.parseInt(st.nextToken());// 들쥐의 초당 이동 거리(1≤100)
		int limit = S * V * S * V * OFF_SET;// 들쥐가 이동 가능한 거리의 제곱
		
		adList = new ArrayList[N + 1];
		match = new int[M + 1];
		visit = new boolean[M + 1];
		
		float mouse[][] = new float[N + 1][2];
		for(int i=1; i<=N; i++)// 들쥐의 좌표가 주어짐
		{
			st = new StringTokenizer(br.readLine());
			mouse[i][0] = Float.parseFloat(st.nextToken());
			mouse[i][1] = Float.parseFloat(st.nextToken());
			adList[i] = new ArrayList<>();
		}
		
		for(int i=1; i<=M; i++)// 땅굴의 좌표가 주어짐
		{
			st = new StringTokenizer(br.readLine());
			float x = Float.parseFloat(st.nextToken());
			float y = Float.parseFloat(st.nextToken());
			
			for(int j=1; j<=N; j++)
			{
				float xx = x - mouse[j][0];
				float yy = y - mouse[j][1];
				int dist = (int)((xx * xx + yy * yy) * OFF_SET);
				if(dist <= limit)
					adList[j].add(i);
			}
		}
		
		int cnt = 0;
		
		for(int i=1; i<=N; i++)
		{
			Arrays.fill(visit, false);
			if(dfs(i))
				++cnt;
		}
		
		System.out.print(N - cnt);
	}
	static boolean dfs(int mouse) {
		for(int hole : adList[mouse])
		{
			if(visit[hole])
				continue;
			
			visit[hole] = true;
			
			if(match[hole] == 0 || dfs(match[hole]))
			{
				match[hole] = mouse;
				return true;
			}
		}
		return false;
	}
}

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 14433 한조 대기 중  (0) 2025.05.14
BOJ 백준 11376 열혈강호 2  (0) 2025.05.11
BOJ 백준 2188 축사 배정  (0) 2025.05.11
BOJ 백준 11375 열혈강호  (0) 2025.05.09

 

문제 : https://www.acmicpc.net/problem/2188

 

[ 문제 요약 ]

  • 일과 사람이 주어지면, 사람과 일을 매칭 시킬 수 있는 최대 수를 출력합니다. 단, 한 사람은 최대 2개의 일을 받아 할 수 있습니다.

 

[ 테스트 케이스 설명 ]

5 5	// 직원수(1<=1,000), 일의수(1<=1,000)
2 1 2	// i번 직원이 할 수 있는 일의 개수와 일의 번호가 주어짐
2 1 2
2 1 2
2 4 5
0
답 : 4

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

 

이 문제는 이분 매칭 알고리즘으로 간단히 풀 수 있습니다.

 

이분 매칭은 두 개의 그룹이 있을 때, 각 그룹의 원소들을 서로 하나씩만 (최대로) 매칭 시키는 알고리즘입니다.

 

실생활에서 많이 쓰이며 dfs를 통해 간단히 구현할 수 있는, 구현에 특정한 틀이 있는 알고리즘입니다.

 

단, 이 문제에서는 한 사람이 두 개의 일을 할 수 있다는 조건이 있습니다.

 

이 문제는 아래 문제와 거의 동일합니다.

https://kyjdummy.tistory.com/50

 

BOJ 백준 11375 열혈강호

문제 : https://www.acmicpc.net/problem/11375 [ 문제 요약 ]직원 수와, 일의 수가 주어지고, 각 직원이 할 수 있는 일의 번호가 주어집니다.이때, 각 직원과 일을 매칭 시킬 때, 매칭 시킬 수 있는 최대 매칭

kyjdummy.tistory.com

 

일에 사람을 매칭 시키는 것으로 보고, 사람을 하나씩 순회하며 어떤 일과 매칭이 가능한지 탐색하는 dfs 함수를 만듭니다.

 

dfs 함수 안에서는 지금 탐색하려는 사람이 정해지지 않은 임의의 job과 매칭이 가능한지 유무를 true, false로 반환합니다. 어떤 job이든 상관없이 job과 매칭이 되는지만 반환합니다.

 

그리고 무한 루프를 방지하기 위해 각 job에 대해 방문 유무를 확인하는 visit 배열이 필요하고, 각 job에 대해 매칭된 사람을 담을 match 배열이 필요합니다.

 

dfs 함수를 돌 때마다 match 배열에는 매칭된 사람이 늘어가게 됩니다. visit 배열은 dfs 함수를 돌 때마다 초기화해줍니다.

 

여기서 한 사람이 2개의 일을 할 수 있다고 했는데, 이건 복잡하게 생각할 것 없이 같은 사람에 대해 dfs 탐색을 두 번 해주면 됩니다.

 

이렇게 해도 되는 이유는, dfs 함수안에서 매칭 가능 유무 탐색시 각 job에 매칭된 사람 번호를 match 배열에 입력하는데, 같은 사람이 들어오던 다른 사람이 들어오던 결국 job이 매칭됐는지 안됐는지만 탐색하고 기록하기 때문에 가능합니다.

 

즉 dfs 함수는, job을 매칭 시키는 게 목표고 job에 어떤 사람을 매칭했는지는 상관하지 않습니다. 그냥 입력된 사람이 job에 매칭이 되냐 안되냐만 반환합니다.

 

dfs를 돌릴 때마다 결국 match 배열에 각 job에 따라 매칭된 사람이 늘어가는 구조입니다. 만약 한 사람이 3번 일을 할당 받을 수 있다면 사람마다 3번의 dfs를 해주면 됩니다.

 

아래 코드는 2개를 제시합니다.

 

첫 번째 코드는 위에서 설명한 내용을 코드로 구현한 것으로 가장 기본적인 구현 방법이고,

 

두 번째 코드는 일반 적인 구현과 반대로 사람에 대해 순회하는 게 아니라, job에 대해 순회합니다.

 

일반적인 구현 방법은 첫 번째 코드입니다.

 

[ 첫번 째 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
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());// 직원수(1<=1,000)
		M		= Integer.parseInt(st.nextToken());// 일의수(1<=1,000)
		match	= new int[M + 1];
		adList	= new ArrayList[N + 1];
		
		for(int i=0; i<=N; i++)
			adList[i] = new ArrayList<>();
		
		for(int person=1; person<=N; person++)
		{
			st = new StringTokenizer(br.readLine());
			int cnt = Integer.parseInt(st.nextToken());

			while(cnt-->0)
				adList[person].add(Integer.parseInt(st.nextToken())); 
		}
		
		int cnt = 0;
		
		for(int person=1; person<=N && cnt < M; person++)
		{
			for(int i=0; i<=1; i++)
			{
				visit = new boolean[M + 1];
				
				if(dfs(person))
					++cnt;
			}
		}
		
		System.out.print(cnt);
	}
	static boolean dfs(int person) {
		for(int job : adList[person])
		{
			if(visit[job])
				continue;
			
			visit[job] = true;
			
			if(match[job] == 0 || dfs(match[job]))
			{
				match[job] = person;
				return true;
			}
			
		}
		return false;
	}
}

 

 

[ 두번째 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

class Main{
	
	static int N, M;
	static ArrayList<Integer>[] adList;		// 일마다 사람번호를 갖고 있음
	static int[][] match;		// [사람번호][0] + [사람번호][1] : 매칭된 job번호
	static boolean[][] visit;	// [사람번호][0] + [사람번호][1] : 방문유무
	
	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());// 직원수(1<=1,000)
		M		= Integer.parseInt(st.nextToken());// 일의수(1<=1,000)
		match	= new int[N + 1][2];
		adList	= new ArrayList[M + 1];
		
		for(int i=0; i<=M; i++)
			adList[i] = new ArrayList<>();
		
		for(int person=1; person<=N; person++)
		{
			st = new StringTokenizer(br.readLine());
			int cnt = Integer.parseInt(st.nextToken());

			for(int j=0; j<cnt; j++)
				adList[Integer.parseInt(st.nextToken())].add(person); 
		}
		
		int cnt = 0;
		
		for(int job=1; job<=M; job++)
		{
			visit = new boolean[N + 1][2];
			if(dfs(job))
				++cnt;
		}
		
		System.out.print(cnt);
	}
	static boolean dfs(int job) {
		for(int person : adList[job])
		{
			for(int i=0; i<=1; i++)
			{
				if(visit[person][i])
					continue;
				
				visit[person][i] = true;
				
				if(match[person][i&1] != job && (match[person][i] == 0 || dfs(match[person][i])))
				{
					match[person][i] = job;
					return true;
				}
			}
		}
		return false;
	}
}

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 14433 한조 대기 중  (0) 2025.05.14
BOJ 백준 2191 들쥐의 탈출  (0) 2025.05.13
BOJ 백준 2188 축사 배정  (0) 2025.05.11
BOJ 백준 11375 열혈강호  (0) 2025.05.09

 

문제 : https://www.acmicpc.net/problem/2188

 

[ 문제 요약 ]

  • 소마다 들어가고 싶어 하는 케이지가 주어집니다.
  • 소들을 케이지에 최대로 넣을 때 넣을 수 있는 소의 최댓값 출력하는 문제입니다.

 

[ 테스트 케이스 해설 ]

5 5	// 소의 수 (1<=200), 축사의 수 (1<=200)
2 2 5	// 각 소가 들어가길 원하는 축사의 수와, 그 축사 번호가 주어짐
3 2 3 4
2 1 5
3 1 2 5
1 2
답 : 4

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

 

이 문제는 이분 매칭 알고리즘으로 간단히 풀 수 있습니다.

 

이분 매칭은 두 개의 그룹이 있을 때, 각 그룹의 원소들을 서로 하나씩만 (최대로) 매칭 시키는 알고리즘입니다. 실생활에서 많이 쓰이며 dfs를 통해 간단히 구현할 수 있는, 구현에 특정한 틀이 있는 알고리즘입니다.

 

여기서는 소를 케이지에 매칭 시키는 것으로 보고, 소를 하나씩 순회하며 어떤 케이지와 매칭 가능한지를 탐색하는 dfs 함수를 작성합니다.

 

dfs 함수 안에서는 지금 탐색하려는 소가 매칭 가능한지를 true, false로 반환합니다.

 

각각의 케이지에 따라 어떤 소가 매칭됐는지를 저장하는 match 배열을 둡니다. match 배열의 인덱스는 케이지 번호고, 그 안에 저장된 값은 소의 번호입니다.

 

특정 소마다 dfs를 항상 돌면서, 이미 케이지에 매칭된 소에게 다른 케이지로 갈 수 있는지 계속해서 물어봅니다.

 

무한 루프에 빠지지 않기 위해, dfs마다 케이지 방문 유무를 확인하는 visit을 두어 모든 케이지를 다 탐색할 때까지 계속해서 다른 케이지로 갈 수 있는지를 물어봅니다.

 

dfs 함수가 최종적으로 true를 반환하면 해당 소를 케이지에 매칭시킬 수 있다는 것이기 때문에 결과에 + 1을 추가합니다.

 

디테일은 코드를 통해 확인 가능합니다.

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

class Main{
	
	static int N, M;
	static int[] match;
	static boolean[] visit;
	static int[][] 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());// 소의 수 (1<=200)
		M		= Integer.parseInt(st.nextToken());// 축사의 수 (1<=200)
		adList	= new int[N + 1][];
		match	= new int[M + 1];
		
		for(int i=1; i<=N; i++)
		{
			st = new StringTokenizer(br.readLine());
			int cnt = Integer.parseInt(st.nextToken());
			adList[i] = new int[cnt];
			
			for(int j=0; j<cnt; j++)
				adList[i][j] = Integer.parseInt(st.nextToken());
		}
		
		int cnt = 0;
		
		for(int i=1; i<=N; i++)
		{
			visit = new boolean[M + 1];
			if(dfs(i))
				++cnt;
		}
		System.out.print(cnt);
	}
	static boolean dfs(int now) {
		
		for(int cage : adList[now])
		{
			if(visit[cage])
				continue;
			
			visit[cage] = true;
			
			if(match[cage] == 0 || dfs(match[cage]))
			{
				match[cage] = now;
				return true;
			}
		}
		
		return false;
	}
}

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 14433 한조 대기 중  (0) 2025.05.14
BOJ 백준 2191 들쥐의 탈출  (0) 2025.05.13
BOJ 백준 11376 열혈강호 2  (0) 2025.05.11
BOJ 백준 11375 열혈강호  (0) 2025.05.09

 

문제 : https://www.acmicpc.net/problem/11375

 

[ 문제 요약 ]

  • 직원 수와, 일의 수가 주어지고, 각 직원이 할 수 있는 일의 번호가 주어집니다.
  • 이때, 각 직원과 일을 매칭 시킬 때, 매칭 시킬 수 있는 최대 매칭 횟수를 출력합니다.

 

[ 테스트 케이스 설명 ]

5 5	// 직원 수(1<=1,000), 일의 수(1<=1,000)
2 1 2	// 각 직원이 할 수 있는 일의 번호
1 1
2 2 3
3 3 4 5
1 1
// 답
4

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

 

이 문제는 이분 매칭 알고리즘으로 간단히 풀 수 있습니다.

 

이분 매칭은 두 개의 그룹이 있을 때, 각 그룹의 원소들을 서로 하나씩만 (최대로) 매칭 시키는 알고리즘입니다. 실생활에서 많이 쓰이며 dfs를 통해 간단히 구현할 수 있는, 구현에 특정한 틀이 있는 알고리즘입니다.

 

여기서는 사람을 일에 매칭 시키는 것으로 보고, 한 사람씩 순회하며 그 사람이 다른 일들과 매칭 가능한지를 탐색하는 dfs 함수를 만듭니다.

 

dfs 함수 안에서는 지금 탐색하려는 사람이 매칭이 가능한지를 true, false로 반환합니다.

 

이 dfs 함수 안에서는 각각의 일에 따른 매칭된 사람 번호를 관리하는 job 배열을 둡니다. job 배열의 인덱스는 일의 번호고, 그 안에 저장된 value가 매칭된 사람 번호입니다.

 

그리고 특정 사람이 매칭 가능한지를 탐색하기 위해 이미 매칭된 다른 모든 사람에게 다른 job으로 이동 가능한지 물어봅니다. 이렇게 모든 사람에 묻기 위해 재귀를 사용합니다.

 

아래는 각각 코드 2개를 보여줍니다.

 

첫 번째 코드는 인접 리스트를 표현 시 List 자료구조를 사용했고, 두 번째 코드는 배열을 사용한 코드입니다.

 

속도가 거의 2배가량 차이 납니다.

 

[ List 사용 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

class Main{
	
	static int N;				// 직원 수
	static int M;				// 일의 최대 수
	static int[] job;			// 각일에 대해 현재 매칭된 사람을 담을 배열, idx가 일의 번호, value가 매칭된 사람
	static boolean[] jobVisit;	// 인덱스가 일의 번호를 의미하며, 해당 일을 방문 해서 체크했는지를 저장
	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());// 직원 수(1<=1,000)
		M		= Integer.parseInt(st.nextToken());// 일의 수(1<=1,000)
		adList	= new ArrayList[N + 1];
		job		= new int[M + 1];
		
		for(int i=0; i<=N; i++)
			adList[i] = new ArrayList<>();
		
		for(int i=1; i<=N; i++)
		{
			st = new StringTokenizer(br.readLine());
			int j = Integer.parseInt(st.nextToken());
			while(j-->0)
			{
				adList[i].add(Integer.parseInt(st.nextToken()));
			}
		}
		
		int cnt = 0;

		for(int person=1; person<=N; person++)
		{
			jobVisit = new boolean[M + 1];
			if(dfs(person))
				++cnt;
		}
		System.out.print(cnt);
	}
	static boolean dfs(int person)
	{
		for(int jobNumber : adList[person])
		{
			if(jobVisit[jobNumber])
				continue;
			
			jobVisit[jobNumber] = true;
			
			if(job[jobNumber] == 0 || dfs(job[jobNumber]))
			{
				job[jobNumber] = person;
				return true;
			}
		}
		return false;
	}
}

 

 

[ 배열 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

class Main{
	
	static int N;				// 직원 수
	static int M;				// 일의 최대 수
	static int[] job;			// 각일에 대해 현재 매칭된 사람을 담을 배열, idx가 일의 번호, value가 매칭된 사람
	static boolean[] jobVisit;	// 인덱스가 일의 번호를 의미하며, 해당 일을 방문 해서 체크했는지를 저장
	static int[][]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());// 직원 수(1<=1,000)
		M		= Integer.parseInt(st.nextToken());// 일의 수(1<=1,000)
		adList	= new int[N + 1][];
		job		= new int[M + 1];
		
		for(int i=1; i<=N; i++)
		{
			st = new StringTokenizer(br.readLine());
			int j = Integer.parseInt(st.nextToken());
			
			adList[i] = new int[j];
			
			while(--j>=0)
				adList[i][j] = Integer.parseInt(st.nextToken());
		}
		
		int cnt = 0;

		for(int person=1; person<=N; person++)
		{
			jobVisit = new boolean[M + 1];
			if(dfs(person))
				++cnt;
		}
		System.out.print(cnt);
	}
	static boolean dfs(int person)
	{
		for(int jobNumber : adList[person])
		{
			if(jobVisit[jobNumber])
				continue;
			
			jobVisit[jobNumber] = true;
			
			if(job[jobNumber] == 0 || dfs(job[jobNumber]))
			{
				job[jobNumber] = person;
				return true;
			}
		}
		return false;
	}
}

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 17481 최애 정하기  (1) 2025.05.14
BOJ 백준 14433 한조 대기 중  (0) 2025.05.14
BOJ 백준 2191 들쥐의 탈출  (0) 2025.05.13
BOJ 백준 11376 열혈강호 2  (0) 2025.05.11
BOJ 백준 2188 축사 배정  (0) 2025.05.11

+ Recent posts