G-S稳定匹配算法详解
GS算法是解决稳定匹配问题(stable matching)的一个优秀的算法。
下面以男女配对的例子来介绍稳定匹配问题并阐述GS算法的具体步骤。
GS算法,全称Gale-Shapley算法。
一、问题描述及假设
-
有n个单身男性集合M = {m1, m2, …, mn}和n个单身女性集合W = {w1, w2, …, wn}
-
假设每个男性对不同女性的喜好程度都不同,单身女性亦如是。
-
男性mi(1 <= i <= n)有一张属于自己的对n个女性的排序表,mi把他最爱慕的女性放在第一位,第二爱慕的女性放在第二位,以此类推,排名越靠前女性表示mi越爱慕的该女性。同样地,女性wi(1 <= i <= n)也有一张属于自己的对n个男性的排序表,排名越靠前的男性越受该女性的喜爱。
-
每个人最终都要有伴侣
二、伪代码
引自《算法设计》(Jon Kleinberg ,Eva Tardos 著 ,张立昂,屈婉玲 译)
三、具体代码
C++实现
#include<iostream>
using namespace std;
// describe where there is a woman is single in a man[a]'s list or not
// if have single woman return 1,else return 0
bool mans_date(int a, bool**b, int number) {
for (int i = 0; i < number; i++)
if (b[a][i] == 0)
return 1;
return 0;
}
// if all the mans have the lovers return 0,else 1
bool have_man(bool*mans_state, int number, int &index) {
for (int i = 0; i < number; i++)
if (mans_state[i] == 0)
{
index = i;
return 1;
}
return 0;
}
// G-S algorithm
// number----the mans and women number
// man ------mans'priority matrix
// women ----women's priority matrix
int* gs(int number, int **man, int **women)
{
//mans and women state describe they are single or not
bool *mans_state = new bool[number];
bool *women_state = new bool[number];
// describe a lovers
int *woman_man_pair = new int[number];
// mans_women describe a man and a women where had date or not
bool **mans_women;
mans_women = new bool*[number];
for (int i = 0; i < number; i++)
mans_women[i] = new bool[number];
//initialize
for (int i = 0; i < number; i++)
{
mans_state[i] = 0;
women_state[i] = 0;
}
for (int i = 0; i < number; i++)
for (int j = 0; j < number; j++)
mans_women[i][j] = 0;
//use inverse to reduce complexity
int **inverse;
inverse = new int*[number];
for (int i = 0; i < number; i++)
inverse[i] = new int[number];
for (int i = 0; i < number; i++)
for (int j = 0; j < number; j++)
inverse[i][women[i][j]] = j;
int index = 0;
while (have_man(mans_state, number, index) && mans_date(index, mans_women, number))
{
int tmp_man = index;
int tmp_woman;
//select the women tmp_man like most and this woman is single
for (int i = 0; i < number; i++)
if (mans_women[tmp_man][man[tmp_man][i]] == 0)
{
tmp_woman = man[tmp_man][i];
break;
}
if (women_state[tmp_woman] == 0)
{
// tmp_man and tmp_woman is not single
women_state[tmp_woman] = 1;
mans_state[tmp_man] = 1;
//tmp_woman's lover is tmp_man
woman_man_pair[tmp_woman]=tmp_man;
//tmp_man and tmp_woman had a date
mans_women[tmp_man][tmp_woman] = 1;
}
else {
//m2-----tmp_woman's lover now
int m2 = woman_man_pair[tmp_woman];
//compair m2 with tmp_man,if tmp_man is more excellent ,tmp_woman will date with tmp_man and break up with m2
if (inverse[tmp_woman][m2] > inverse[tmp_woman][tmp_man])
{
//tmp_woman's lover is tmp_man
woman_man_pair[tmp_woman] = tmp_man;
//m2 back to single
mans_state[m2] = 0;
//tmp_man is not single
mans_state[tmp_man] = 1;
//tmp_woman's lover is tmp_man
mans_women[tmp_man][tmp_woman] = 1;
}
else {
//tmp_man and tmp_woman had a date
mans_women[tmp_man][tmp_woman] = 1;
}
}
}
//return the woman mans'like in man'order
int *end_pair = new int[number];
for (int i = 0; i < number; i++)
end_pair[woman_man_pair[i]] = i;
return end_pair;
}
int main() {
int number, **mans, **women;
cout << "input the number of man or woman:";
cin >> number;
mans = new int*[number];
women = new int*[number];
//initialize
for (int i = 0; i < number; i++)
{
mans[i] = new int[number];
women[i] = new int[number];
}
cout << "input mans' priority matrix" << endl;
for (int i = 0; i < number; i++) {
for (int j = 0; j < number; j++)
cin >> mans[i][j];
}
cout << "input women's priority matrix" << endl;
for (int i = 0; i < number; i++) {
for (int j = 0; j < number; j++)
cin >> women[i][j];
}
for (int i = 0; i < number; i++) {
for (int j = 0; j < number; j++)
{
mans[i][j] -= 1;
women[i][j] -= 1;
}
}
cout << endl << endl;
int*end_pair2 = new int[number];
end_pair2 = gs(number, mans, women);
for(int i=0;i<number;i++)
cout <<end_pair2[i]+1<<" ";
return 0;
}
其中使用了反转的思想实现降低时间复杂度的需要
四、输入输出
输入:
输出:
3 1 2 5 4
经验证,是稳定匹配
五、总结
对于男性而言,G-S算法是最理想的,因为男性匹配到的都是最佳有效伴侣(best(m))
而对于女性来说匹配到的最差有效伴侣(worst(w))
虽然男性可能常常会被拒绝的一方,是但是只要不断尝试,最终得到的结果就是最美好的
这启示我们不管追寻爱情还是做其他事前,应该积极主动一点才会有最好的结局。