题意:男女各n人,进行婚配,对于每个人来说,所有异性都存在优先次序,即最喜欢某人,其次喜欢某人...输出一个稳定婚配方案。所谓稳定,就是指未结婚的一对异性,彼此喜欢对方的程度都胜过自己的另一半,那么这对异性就有私奔的可能性。
这里明显也是一个匹配问题,与最佳二分完美匹配所不同的是,二分匹配重在求最佳权值,而这里求的是满足彼此的要求。这里用到了Gale-Shapley算法。
算法学习:http://wenku.baidu.com/view/964a503843323968011c92c3.html
http://wenku.baidu.com/view/7aa841f2fab069dc502201cb.html
前者描述详细,值得一看;后者虽然描述不够清晰,但给出了优劣势的证明,并且对第一篇文章倒数第三段提到的“欺诈与博弈”给出了具体样例,可以借鉴。
先把代码贴出来,其实就是贪心的思路,模拟一下这种操作方式,O(n2)的复杂度,已经是输入复杂度了,不能再省了。
uva挂了,所以不保证code的正确性。
1 #include2 #include 3 #include 4 using namespace std; 5 #define Clear(f, nr) memset(f, nr, sizeof(f)) 6 const int SIZE = 1008; 7 const int INF = 1 << 30; 8 int n; 9 int men[SIZE][SIZE], wmen[SIZE][SIZE]; 10 int menChs[SIZE]; //女生的选择 11 int que[SIZE * SIZE]; 12 bool vis[SIZE][SIZE]; 13 void StableMarriage() 14 { 15 int front = 0, rear = 0; 16 Clear(menChs, -1); 17 Clear(vis, 0); 18 for(int i = 1; i <= n; i ++) 19 que[rear ++] = i; 20 21 while(front < rear) { 22 int tmp = que[front ++]; 23 for(int i = 1; i <= n; i ++) { 24 if(!vis[tmp][wmen[tmp][i]]) { 25 vis[tmp][wmen[tmp][i]] = 1; 26 if(menChs[wmen[tmp][i]] == -1) { 27 menChs[wmen[tmp][i]] = tmp; 28 break; //忘加一个break改了一个小时 29 } 30 else { 31 int mark = menChs[wmen[tmp][i]]; 32 if(men[wmen[tmp][i]][mark] < men[wmen[tmp][i]][tmp]) { 33 menChs[wmen[tmp][i]] = tmp; 34 que[rear ++] = mark; 35 break; 36 } 37 } 38 } 39 } 40 } 41 42 return ; 43 } 44 void Print() 45 { 46 for(int j = 1; j <= n; j ++) 47 for(int i = 1; i <= n; i ++) 48 if(menChs[i] == j) 49 cout << i << endl; 50 } 51 int main() 52 { 53 int T, x; 54 cin >> T; 55 int gg = 0; 56 while(T --) { 57 if(gg ++) puts(""); 58 cin >> n; 59 for(int i = 1; i <= n; i ++) 60 for(int j = 1; j <= n; j ++) 61 cin >> wmen[i][j]; //女生记邻接表 62 for(int i = 1; i <= n; i ++) 63 for(int j = 1; j <= n; j ++) { 64 cin >> x; 65 men[i][x] = n - j; //男生记邻接阵 权值 66 } 67 StableMarriage(); 68 Print(); 69 } 70 }
同样还是用自己的话描述一下:
一、首先给出算法:依据优先次序,男生在第一轮分别向自己最喜欢的女生求婚,女生对于求婚,总是从中选择最理想的人选。一轮结束后,男生的结果是求婚成功或者被拒。第二轮,单身们继续追求真爱,向各自喜好的排在第二的人求婚(不管对方是否有男伴),女生同样是选择最理想的人选。这一轮结束后,男生的结果是求婚成功、被拒,又或是被其他男人抢走女伴,重新沦为单身。第三轮...直到不存在单身男子为止。
二、为什么这样就能得到“稳定”的方案呢?
在算法运行结束后,对于一对(x,y),男生x是按优先次序,从高到低向女生求婚,之前的女生都拒绝了他,才会与y成婚。假设仍存在不稳定,那么相比于y,会使男生x私奔的只有那些拒绝了x的女生,由算法可知,女生拒绝x的理由是她们有更优的人选,所以女生们没有理由跟x私奔,假设失败。所以Gale-Shapley算法一定能得到稳定方案。
三、进一步讨论:优势问题。看似对男生残酷(不断地表白)的选择方式,其实最终得到的方案,是在稳定前提下,男生的最优方案。相对应的,对女生而言是最差的方案。
“男生最优”其实不难理解,因为男生x是按优先顺序表白的,比成婚对象y更理想的女生都拒绝了x,理由是有了比x更好的x'。若是对男生而言,还存在更优方案,那么只能去“强迫”拒绝了x的女生y',组成(x,y')。可是对于x'而言,被x替换掉以后只能找不如y'的女生成婚了,不稳定也就出现了:(x',y')会私奔。所以不会有更优方案,原方案就是“男生最优”。
“女生最劣”不好理解,不过可以仿照上述分析。对于女生而言,若还有更劣势的情况,只能是女生y还可能和不如x的男生x'成婚,组成(x',y),这里注意,那么x在被拒之后,只能去追求不如y的女生,不稳定也就出现了:(x,y)会私奔,所以不会有更劣方案,原方案已经是“女生最劣”。
另一种抽象的解释:已知在稳定条件下,对于男生、女生,方案的优劣都有上下界。在方案未定之前,整个系统是不稳定的(仍有单身,说明跟别人抢老婆失败了= =)。男生逐渐降低自己的要求(逼近上界),主动出击,寻求最理想的真爱;女生被动接受,在选择她的众多男生中选择最佳(逼近下界)。当系统稳定(单身消失),男女生的选择分别是在稳定条件下的最优、最劣。(注意,女生最后的组合(x,y),虽然x不一定是最差的,但是比x好的都被其他女生抢走了,没能向y表白)
优劣只是相对而言,交换顺序,就是女生主动、男生被动,最终方案就是“男生最劣”、“女生最优”。
四、“欺诈与博弈”
既然“女生最劣”,是不是可以有更优解呢?这就要欺诈。
男 女
1:BADC A:1234
2:ABCD B:2143
3:BCAD C:3241
4:ADBC D:4231
原本按照G-S算法,第一轮结束的结果是:(2,A),(1,B),3、4分别被B,A拒绝了;最终结果是(2,A)(1,B)(3,C)(4,D)。若A,B提前了解了每个人的优先序列,进行欺诈,在第一轮选择(4,A),(3,B),虽然A,B暂时配偶不理想,但是最终结果:(1,A)(2,B)(3,C)(4,D)对于女生而言是最优解。
五、局限
G-S算法的基础,是将数据分为两个集合(数量不一样,就不能依照“单身消失”这一条件结束,而应该判断全部单身男子是否访问完各自的优先序列),由一个集合主动,另一个被动。若集合数>2,就不存在绝对的主动、被动:x选择y,可能y去选择z。例如寝室分配,2n个人分n个寝室,每个人对其他(2n-1)人有喜恶,就不能用G-S算法解决。(想想看,若是在婚配问题上,就是说每个男生的优先序列上除了女生,还混进了(n-1)个男生...)事实上,它本身很可能不存在稳定方案,具体看第一篇文章的倒数第二段。
六、拓展
G-S算法中,后者“S”所表示的Shapley在2012年获得诺贝尔经济学奖,以下是相关介绍,主要研究算法部分。
http://wenku.baidu.com/view/da999a2c4b35eefdc8d33354.html
从第四页的“(二)稳定配置理论”开始(前面的经济术语恶心死了),介绍了两种合作博弈的算法:Gale-Sharpley算法和顶端交易循环算法。其中G-S算法除了“存在性”,“最优性”外,还介绍了“唯一性”:当且仅当男人的最优匹配和女人的最优匹配一致时,稳定条件下只包含唯一解。
G-S算法用于解决“双边市场”的问题(男女各有所需),对于“单边市场”,即只有一侧存在需求(想象一下女生不会拒绝的情况),要用到“顶端交易循环算法”,例2中有详细介绍。(通俗来讲,都用到贪心的思想)
首先明确“单边市场”下的稳定指的是什么:n个人选择n件物品,A选1,B选2,不会同时存在A更喜欢2,B更喜欢1,否则他们就可以交换(交易),即不稳定。
给出算法:首先随意分配n件物品到n个人手中,随意选一个人,找到其优先序列中的第一件物品,观察该物品现在在谁手上,两个人之间构成有向边(纯粹是为了好表达才用有向边描述),重复建边过程,必然会产生一个环,环上的人通过彼此交换物品,可以实现每个人都获得最想要的物品。至此,一轮结束,环上的人及其物品不再考虑,其余人优先序列上去除这些物品。重复操作,直到所有人退出。
为什么能成环就不用解释了,注意如果自己手上拿着的就是最想要的物品,构成自环,同样退出考虑范围。
为什么这样就稳定呢?
沿着算法的思路,第一轮退出的人不存在不稳定的可能,他们拿到了最理想的物品,没有人可以和他们交换。那么对于第一轮留下的全部人而言,第二轮退出的人不存在不稳定的可能,这些人要么拿到最理想的物品,要么拿到次理想的物品(最理想的物品被第一轮的人拿走了),第二轮留下的人不存在与这些人交换的可能。以此类推,方案稳定。
例3、例4、例5都挺有意思,不过我认为真正要注意的不仅仅是分配的方法,还有判断不稳定的条件,什么是真正的公平我们不能一概而论,但如何能在某一方面实现相对公平才是要讨论的。就比如例4中提到的,五家合起来修路,若还不如两家合起来划算,为何还要五家一起。(例4让我又想到了电梯付费,是一个道理)
还有一点疑问,就是文章中“罗斯对NRMP的重新设计,确保已婚医生夫妇也能实现稳定的匹配”。究竟是怎样的?是不是把夫妇二人缩成一个点就可以了?