unagi11
이국의 보조기억장치
unagi11
전체 방문자
오늘
어제
  • 전체 글 (35)
    • Technology (28)
      • Algorithm Theory (10)
      • Problem Solving (14)
      • Unreal (1)
      • Unity (1)
      • Cocos2d (0)
      • etc (2)
    • Develop (5)
      • Dungeon-Chess (0)
      • Past Projects (3)
      • etc (2)
    • Daily (2)

블로그 메뉴

  • 깃허브
  • 프로필

인기 글

최근 글

hELLO · Designed By 정상우.
unagi11

이국의 보조기억장치

Technology/Algorithm Theory

[Algorithm] 최대 이분 매칭 문제

2022. 6. 6. 23:54

문제

Given a bipartite undirected graph G=(XUY, E), find the maximum-cardinality matching M*.
주어진 이분 비방향 그래프 G에서 (중복되지 않는) 최대 매칭 집합크기를 구해라.



Matching이란?

A subset M of E is called Matching if no two edges in M are adjacent in G.
E의 부분집합 M에 인접한 두 edge가 존재하지 않는다면, M은 Matching이라고 부른다.



성질

In a bipartite undirected graph G=(XUY,E), if every vertex has degree k>0, then there exists a perfect matching M.
이분 매칭에서 모든 정점이 같은 차수라면, 완전 매칭이 존재한다.

i.e., the maximum-cardinality matching M* satisfies that |M*| = |X| = |Y|
퍼펙트 매칭에서 매칭 최대 개수는 |M*| = |X| = |Y|를 만족한다.



해결방법 1 (최대 유량 문제)

최대 유량 문제로 치환 가능하다 (Ford_Fulkerson, Edmond karp 알고리즘)
1. Generate a source s and a sink t. 시작점 s와 끝점 t를 생성한다.
2. For each x in X, add edge from s to x with capacity 1. s에서 x로 용량 1의 간선을 만든다.
3. For each y in Y, add edge from y to t with capacity 1. y에서 t로 용량 1의 간선을 만든다.
4. For each edge xy in E, add edge from x to y with capacity 1. 모든 xy 간선을 용량 1로 만든다.
5. s에서 t까지 최대한 보낼수 있는 유량을 계산하면, 이는 곧 최대 매칭 개수와 같다.



해결방법 2 (DFS)

// DFS 기반 최대 이분 매칭 코드

#include <vector>

using namespace std;

typedef vector<vector<int>> adjList;

#define N 10 // N = |A| : A 그룹의 크기
#define M 10 // M = |B| : B 그룹의 크기

adjList vt;      // vt[a] : a와 연결된 b들 인접리스트
bool visited[N]; // for all a in A. a를 방문했는가.
int Match[M];    // for all b in B. b와 매칭되는 a의 index.

bool DFS(int a)
{
    if (visited[a])    // 방문한적 있다면 반복하지 않는다.
        return false;  // a는 짝을 못찾았다.
    visited[a] = true; // 방문 체크한다.

    for (int b : vt[a]) // a와 연결된 모든 b에 대해서
    {
        // 만약 짝이 없거나, b의 짝a가 다른 b를 찾을수 있다면
        if (Match[b] == -1 || DFS(Match[b]))
        {
            Match[b] = a; // b의 짝을 현재 a로 바꿔준다.
            return true;  // a는 짝을 찾았다.
        }
    }

    return false; // a는 짝을 못찾았다.
}

int MaxMatching()
{
    int ans = 0; // a와 b의 최대 매칭 개수

    fill(Match, Match + M, -1); // 매칭되지 않은 리스트를 -1로 초기화한다.
    for (int i = 0; i < N; i++) // N을 순회하면서 짝을 찾는다.
    {
        fill(visited, visited + N, false);
        if (DFS(i)) // i번째 a는 짝을 찾았다.
            ++ans;
    }

    return ans;
}
저작자표시 변경금지 (새창열림)
    'Technology/Algorithm Theory' 카테고리의 다른 글
    • [Algorithm] Spanning Tree
    • [Algorithm] 최대 유량 문제
    • [Algorithm] Backtracking
    • [Algorithm] Sieve of Eratosthenes
    unagi11
    unagi11
    개발하고 기록하자

    티스토리툴바