Algorithm

Bipartite Match [c++]

PON_Z 2021. 1. 27. 19:16

 이분매칭(bipartite match)은 A집단이 B집단을 선택하는 방법에 대한 알고리즘이다.

 

 사람의 집단을 A, 노트북의 집단을 B라고 할 때 이를 그래프로 나타내면 아래와 같다.

 

 

 위와 같이 각 집단에 원하는 항목이 있을대 가장 효과적으로 매칭 시키는 알고리즘, 즉 최대 매칭(Max Matching)을 수행하는 알고리즘이다. 다시 말해서 모든 사람이 각각 노트 북을 선택하여 가장 많이 연결 되는 경우의 수를 찾는 것이다.

 

이는 용량(Capacity)가 1인 네트워크 플로우 문제로도 해석 할 수 있다, 다만 에드몬드 카프 알고리즘은 시간 복잡도가

O(V + E^2) 이기 때문에 이분매칭에 한해 더 빠르고 효율적인 DFS를 활용한 방법으로 구현 할 것이다.

 

1. 동빈은 A를 선택한다.

2. 태일은 A를 선택 해야하지만 이미 동빈이 선택해 있으므로, 동빈이 A를 제외한 다른 노트북을 선택할 수 있는지 찾아본다. 여기서는 다른 노트북 B를 선택 할 수 있으므로 동빈이 B, 태일이 A를 선택하도록 한다.

3. 한울은 B를 선택해야 하지만 이미 동빈이 선택해 있으므로, 위와 같은 방식으로 동빈이 C, 태일이 A, 한울이 B를 선택하도록 한다.

 

#include <iostream>
#include <vector>
#define MAX 101

using namespace std;

vector<int> a[MAX];

bool c[MAX]; // 특정한 정점의 정보
int d[MAX]; // 점유하고 있는 노드의 정보 


int n = 3, m; // 정점의 개수, 간선의 개수


// 매칭에 성공한 경우 True, 아니면 false
bool dfs(int x) {
for (int i = 0; i < a[x].size(); i++) {
int t = a[x][i];
// 이미 처리한 노드는 볼 필요 없음
if (c[t]) continue;
c[t] = true;

// 비어있거나 점유노드에 더 들어갈 공간이 있는 경우
if (d[t] == 0 || dfs(d[t])) {
d[t] = x;
return true;
}
}
return false;
}

int main() {
a[1].push_back(1);
a[1].push_back(2);
a[1].push_back(3);
a[2].push_back(1);
a[3].push_back(2);

int count = 0;
for (int i = 1; i <= n; i++) {
fill(c, c + MAX, false); // dfs할 때마다 c 초기화
if (dfs(i)) count++;
cout << d[1] << d[2] << d[3] << endl;
}
cout << count << "개의 매칭이 이루어졌습니다." << endl;
for (int i = 1; i <= 100; i++) {
if (d[i] != 0) {
cout << d[i] << " -> " << i << endl;
}
}
}

 

 

 

 

 

728x90

'Algorithm' 카테고리의 다른 글

Rabin-Karp [c++]  (0) 2021.02.03
Strongly Connected Component [c++]  (0) 2021.01.29
Topology Sort [c++]  (0) 2021.01.21
Floyd Warshall [c++]  (0) 2021.01.19
Dijkstra [c++]  (0) 2021.01.15