算法的优雅(五):平衡的爱情
首先,关于这个问题我以前写过的,不过这次想细致的整理一下,算法高手可以无视了,毕竟二分图匹配问题都太基础了.....准备工作或者考研的可以看看,图论问题还是很不错的question.
二分图稳定匹配是图论的一种,也可以算是网络流的一种特型,至于网络流的问题,以后会开一章去讨论的,而这章我们主要讨论这个有趣的问题。
在大学恋爱中,我们不得不面对一个问题,那就是被撬了.....被撬了主要原因是你对象喜爱第三者的程度大于你,如果第三者有对象,那么他喜爱他对象的程度小于你对象,我们可以将这个简化成一个模型。
在一个社团里有n位女士和n位男士,这样是为了防止单身的出现。每位女士按照其对每位男士作为配偶的偏爱程度给每位男士排名。不允许并列名次出现,因此,如果一位女士在两位男士之间分不出差别,我们还是要求她表示出某种偏爱。这种偏爱应是纯顺序的,这样每位女士将这些男士排成顺序1,2,3....,n。类似地,每位男士也将这些女士排成顺序1,2,3...,n。使这些男士和女士配成完备婚姻的方式有n!种。如果存在两位女士A和B及两位男士a和b,使得
1.A和a结婚。
2.B和b结婚。
3.A更偏爱b(名次更优先)而非a。
4.b更偏爱A而非B。
那么我们说这个完备的婚姻是不稳定的。因此,在不稳定的完备婚姻中,A和b可能背着别人相伴逃走,因为他俩都认为,与当前配偶比起来每人都更偏爱各自的新伴侣。因此,一男一女以对他们双方都有利的方式共同行动而打乱婚姻的情况下,这种完备婚姻是“不稳定的”。如果完备婚姻不是不稳定的,则称其为稳定的。由此产生的第一个问题是:是否总存在稳定的完备婚姻?
再一次用二分图来为这个问题建立数学模型。另G=(X,Y)是一个二分图,其中
X={w1,w2,......,wn}
为n位女士的集合,而
Y={m1,m2,.....,mn}
为n为男士的集合。将每一个女顶点(女士在左边)链接到每一个男顶点(男士在右边)。所得的二分图在包含双方顶点集之间的所有可能的边的意义下是完备的(也就是完全二分图)。对应每条边{wi,mj},存在一个数对p,q,其中p表示在wi给男士排序中mj的位置,q表示在mj给女士排序中wi的位置。这些女士和男士的完全婚姻对应二分图G的(n条边的)完美匹配。
在记法上,使用优先秩评定矩阵所提供的模型会更方便。该矩阵为一n行n列的阵列,n行对应每一位女士w1,w2,....,wn,n列对应每一位男士m1,m2,....,mn。在第i行和第j列交叉位置处放上分别代表wi给mj排的名次和mj给wi排的名次的数对p,q。一个完备婚姻对应该矩阵上n个位置的集合,该集合恰好包含每一行的一个位置和每一列的一个位置(经典的N车问题)。
对于每一个优先秩评定矩阵都存在稳定的完备婚姻证明:
我们定义一中确定完备婚姻的算法——延迟认可算法(Gale-Shapley算法)
从每一个女士被标记落选记号开始。
当存在落选女士时,做:
1.每一位落选的女士在所有尚未拒绝她的男士中选择一位被她排名最优先的男士。
2.每一位男士在所有已经选择他并且他尚未拒绝的女士中挑选被他排名最优先的女士,对她推迟决定,并于此时拒绝其余女士。
于是,在算法执行期间,女士向男士求婚(小受?!),一些男女订婚,但是,如果收到更好的求婚,男士可以悔婚。一旦男士订婚,他就在算法执行始终保持订婚状态,但是他的未婚妻可以改变;在他看来这种改变总是一中改进。然而,女士则在算法执行期间可以订婚若干次;每一次新的订婚对她来说都将导致更不理想的伴侣。从算法的描述得出,只要不存在被拒绝的女士,那么每一位男士就恰与一位女士订婚,并且由于男女人数相同,每一位女士也恰与一位男士订婚。现在将每一位男士与他订婚的女士配成一对并得到一种完备婚姻。现在我们证明该完备婚姻是稳定的。
考虑女士A和B及男士a和b,使A和a配对,B和b配对,但是A更偏爱b而不是a。我们证明b不可能比起偏爱B来更偏爱A。由于在算法的某个阶段A在a,b间更偏爱b,A选择b,但A因为b将某位女士排的更优先而被b拒绝。但是,在算法过程中与男士b配对的女士实际上至少与他拒绝过的任何女士有同等级的优先级。既然A被b拒绝过,b必然更偏爱B而不是A。因此,不存在不稳定的配对,该完备婚姻是稳定的。
上面的模拟过程是完全按照社会情况模拟的,女生大部分处于挑选状态,而男生大多处在被动的状态,不过像定亲和女追男是存在的,不过由上面模拟过程可以看出来,如果想让该部分达到稳定,那么女生每次因为配偶不满意而发生改变的时候都会遇到更糟糕的配偶,但如果得到更优秀的配偶那么必然存在不稳定因素了,所以,这也是一种教育啊.......
代码:
#include <cstring>
#include <stdio.h>
#include <string>
#include <cmath>
#include <queue>
#include <map>
#include <memory>
#include <iostream>
using namespace std;
map<string, int> bmap, gmap;
string bname[501], gname[501];
int bpre[501[501]; //used to store boys' prefrence, bpre[i][j] = k means to boy i, he ranks the girl k in jth place, the girl k is his jth choice.
int gpre[501][501]; //used to store girls' prefrence, gre[i][j] = k means to girl i, she ranks the boy j in the kth place//(different from the storing way of bpre[][], because to boys, they traverse girls from highest to lowest; //but to girls, they need to quickly get to know one boy's rank)
int gres[501]; //used to store girls' result, gres[i]=j means girl i is with boy j
int bres[501];
char input[1500];
int n;
queue<int> bqueue;int main(){while(~scanf("%d",&n)){memset(gres,-1,sizeof gres);memset(bres,-1,sizeof bres);getchar();bmap.clear();gmap.clear();int gcount = 0, i = 0, j = 0;int index = 0;for(i = 1;i <= n;i++){scanf("%s", input);bname[i] = input;bmap[input] = i;bqueue.push(i);bpre[i][0] = 1; //b[i][0] store thes ranking number of the girl whom this boy is asking, every boy starts from the 1st girl.for(j = 1;j <= n;j++){scanf("%s",input);if(gmap[input] == 0){index++;gmap[input] = index;gname[index] = input;}bpre[i][j] = gmap[input];}}for(i = 1;i <= n;i++){scanf("%s", input);int gindex = gmap[input];for(j = 1;j <= n;j++){scanf("%s",input);gpre[gindex][bmap[input]] = j; //store the rank, the smaller, the higher the propriety will be.}}int bindex = 0, gaskindex = 0;while(!bqueue.empty()){bindex = bqueue.front();//cout << "current boy's name: "<< bname[bindex] <<endl;bqueue.pop();gaskindex = bpre[bindex][bpre[bindex][0]];if(gres[gaskindex] < 0){gres[gaskindex] = bindex;bres[bindex] = gaskindex;}else if(gpre[gaskindex][bindex] < gpre[gaskindex][gres[gaskindex]]){bqueue.push(gres[gaskindex]);bpre[gres[gaskindex]][0] = (bpre[gres[gaskindex]][0]+1) % (n+1);gres[gaskindex] = bindex;bres[bindex] = gaskindex;}else{bqueue.push(bindex);bpre[bindex][0] = (bpre[bindex][0]+1) % (n+1);}}for(i = 1;i <=n ;i++){cout<<bname[i]<<' '<<gname[bres[i]]<<endl;}}return 0;
}
算法的优雅(五):平衡的爱情相关推荐
- 浅谈算法和数据结构: 五 优先级队列与堆排序
原文:浅谈算法和数据结构: 五 优先级队列与堆排序 在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏 ...
- 算法复习第五章贪心法
算法复习第五章贪心法 概述 TSP 最近邻点策略 最短连接策略 图着色问题 最小生成树(Prim算法.Kruskal) 0-1bag问题 活动安排问题 多机调度 概述 TSP 最近邻点策略 最短连接策 ...
- 萌新卷妹带你逃出算法无名岛第五站
萌新卷妹带你逃出算法无名岛第五站
- JS toFixed的使用误差,银行家算法(四舍六入五取偶)实现
JS toFixed的使用误差,银行家算法(四舍六入五取偶)实现 前言 toFixed方法 "四舍六入五取偶" 问题 银行家算法实现 扩展 原因 解决方式 附注 前言 JS是一门弱 ...
- Java 数据结构和算法(十五):无权无向图
Java数据结构和算法(十五)--无权无向图 前面我们介绍了树这种数据结构,树是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合,把它叫做"树"是因为它看起 ...
- 算法笔记(五)数论、进制、位运算、统计抽样、计算几何
layout: post title: 算法笔记(五)数论.进制.位运算.统计抽样.计算几何 description: 算法笔记(五)数论.进制.位运算.统计抽样.计算几何 tag: 算法 算法笔记( ...
- CSK与KCF算法推导(五)
本文是CSK与KCF算法推导的第五篇,主要介绍具体实现的细节. CSK与KCF算法推导(一)--DFT.相关运算和循环卷积 CSK与KCF算法推导(二)--带核函数的岭回归问题求解 CSK与KCF ...
- 蓝桥杯 试题 算法训练 娜神平衡 C++ 详解
问题描述: 娜娜是一个特别可爱的女孩子,作为学神的她最近在情感方面出现了一点点小问题. 她暗恋的琦琦是一名学霸,他只喜欢长得漂亮和学习很好的女生. 娜娜学习确实很神,但是她在琦琦面前却总是表现不出平时 ...
- 参考Box2d算法实现的一个平衡球游戏
愤怒的小鸟像一阵旋风样刮便了大江南北,在惊异于游戏可爱的画面的有趣的音效的同时,本人比较感兴趣的还有那些木头.石头倒塌的效果是怎么实现的.后来发现这一切都源自于一个叫Box2d的物理引擎,有意思. 最 ...
最新文章
- 微信的Bug差点让我被老板炒鱿鱼!
- FPGA和DSP间基于SRIO的高速通信系统设计
- ds查找—二叉树平衡因子_面试官让我手写一个平衡二叉树,我当时就笑了
- 一个asp.net2005的页面文件调用CSS样式的BUG
- 解决VS2015 VBCSCompiler.exe 占用CPU100%的问题
- 安装ie9提示未能完成安装_IE9浏览器无法安装怎么办?如何解决?
- AnnotationConfigApplicationContext容器初始化
- 我的 intellij idea 设置
- java 构造块_java中构造方法、普通块、静态代码块、构造块的执行顺序
- Rust之控制流,条件语句,模式匹配
- STM32串口通信实例
- 单个文件如何修改MD5
- android3d画廊自动切换,Android ViewPager打造3D画廊
- 解决U盘复制拷贝文件过大不能超过4G的方法
- Golang interface 全面介绍
- 刻意练习这本书。。。。。。。
- php中subtr()函数的使用方法
- PDPS软件:PSZ格式文件的保存与打开方法
- Taste/Thoth:Taste Architecture 概览【转Beyond Search】
- POS--权益证明机制
热门文章
- 婚庆行业小程序标准版
- crmeb知识付费uniapp重构 适配小程序 APP 微信H5
- final_cut_pro基础
- 你对本岗位的认识PHP,本岗位工作认识
- 大阪第83天——可怕的日本(转贴)
- 三个数差的平方公式推导过程_平方差公式证明推导过程及运用详解(数学简便计算方法之一)...
- 论文笔记2:Combining Lexical, Syntactic, and Semantic Features with Maximum Entropy Models for Extracting
- 非参数统计中的核平滑方法/Kernel smoother
- c语言c 哪个好学,C语言好学吗?
- 在使用pyplot时报错MatplotlibDeprecationWarning