알고리즘 문제
백준 2186 축사 배정 C++ 기록
als982001
2023. 1. 26. 20:23
https://www.acmicpc.net/problem/2188
2188번: 축사 배정
농부 존은 소 축사를 완성하였다. 축사 환경을 쾌적하게 유지하기 위해서, 존은 축사를 M개의 칸으로 구분하고, 한 칸에는 최대 한 마리의 소만 들어가게 계획했다. 첫 주에는 소를 임의 배정해
www.acmicpc.net
이 문제는 최대한 많은 수의 소가 축사에 배정될 때의 소의 수를 구하는 문제이다. 이는 전형적인 이분 매칭 문제이다. 이분 매칭은 이 곳(https://blog.naver.com/ndb796/221240613074)을 참고하였다.
- 소와 축사 수를 입력 받는다. 그리고 각 소별로 원하는 축사들을 입력받고 저장한다.
- 각 소별로 축사를 배정할 수 있는지 검사한다.
- 현재 소가 원하는 축사들을 전부 검사한다.
- 만약 이미 배정된 축사라면, 그 축사는 검사를 패스한다.
- 만약 아직 배정된 소가 없거나, 그 소를 다른 축사로 옮길 수 있다면 이 축사에 현재 소를 배정허고 true를 반환한다.
- 끝까지 배정되지 않은 경우 false를 반환한다.
- 만약 배정에 성공하였다면 answer의 값을 1 증가시킨다.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <memory.h>
#include <deque>
#include <cmath>
#include <stack>
#include <cstring>
#include <typeinfo>
#include <iomanip>
#include <limits.h>
#pragma warning(disable:4996)
using namespace std;
#define MAX 201
int answer = 0; // 가장 많이 배정된 소의 수
int cowNum, cattleShedNum; // 각각 총 소의 수, 축사 수
bool isMatched[MAX]; // 축사가 배정되었다면 true, 아니면 false
int whichCow[MAX]; // 각 축사별 소
vector<int> hopes[MAX]; // 각 소들이 원하는 축사들
bool Match(int cow)
{
// 3. 현재 소가 원하는 축사들을 전부 검사한다.
for (int i = 0; i < hopes[cow].size(); ++i)
{
int cattleShed = hopes[cow][i]; // 소가 원하는 축사
// 3-1. 만약 이미 배정된 축사라면 패스한다.
if (isMatched[cattleShed] == true)
continue;
isMatched[cattleShed] = true;
// 3-2. 만약 아직 배정된 소가 없거나, 그 소를 다른 축사로 옮길 수 있다면
// 이 축사에 현재 소를 배정허고 true를 반환한다.
if (whichCow[cattleShed] == 0 || Match(whichCow[cattleShed]))
{
whichCow[cattleShed] = cow;
return true;
}
}
// 3-3. 끝까지 배정되지 않은 경우 false를 반환한다.
return false;
}
int main()
{
ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
// 1. 소와 축사 수를 입력 받는다.
// 그리고 각 소별로 원하는 축사들을 입력받고 저장한다.
cin >> cowNum >> cattleShedNum;
for (int cow = 1; cow <= cowNum; ++cow)
{
int hopeNum; // 소별로 원하는 축사의 수
cin >> hopeNum;
for (int h = 0; h < hopeNum; ++h)
{
int cattleShed; // 소가 원하는 축사 번호
cin >> cattleShed;
hopes[cow].push_back(cattleShed); // 저장
}
}
// 2. 각 소별로 축사를 배정할 수 있는지 검사한다.
for (int cow = 1; cow <= cowNum; ++cow)
{
memset(isMatched, false, sizeof(isMatched));
// 4. 만약 배정에 성공하였다면 answer의 값을 1 증가시킨다.
if (Match(cow)==true)
++answer;
}
cout << answer << endl;
return 0;
}
참고: https://blog.naver.com/ndb796/221240613074
29. 이분 매칭(Bipartite Matching)
지난 번에 네트워크 플로우(Network Flow) 알고리즘에 대해 공부하는 시간을 가졌습니다. 이...
blog.naver.com