G-S稳定匹配算法详解

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个男性的排序表,排名越靠前的男性越受该女性的喜爱。

  • 每个人最终都要有伴侣


二、伪代码

image-20200302163507613

引自《算法设计》(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))

虽然男性可能常常会被拒绝的一方,是但是只要不断尝试,最终得到的结果就是最美好的

这启示我们不管追寻爱情还是做其他事前,应该积极主动一点才会有最好的结局。

发布了40 篇原创文章 · 获赞 57 · 访问量 2776

猜你喜欢

转载自blog.csdn.net/weixin_44984664/article/details/104615067