Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1959 | Accepted: 835 |
Description
The stable marriage problem consists of matching members of two different sets according to the member’s preferences for the other set’s members. The input for our problem consists of:
- a set M of n males;
- a set F of n females;
- for each male and female we have a list of all the members of the opposite gender in order of preference (from the most preferable to the least).
A marriage is a one-to-one mapping between males and females. A marriage is called stable, if there is no pair (m,f) such that f ∈ F prefers m ∈ M to her current partner andm prefers f over his current partner. The stable marriage A is called male-optimal if there is no other stable marriage B, where any male matches a female he prefers more than the one assigned in A.
Given preferable lists of males and females, you must find the male-optimal stable marriage.
Input
The first line gives you the number of tests. The first line of each test case contains integer n (0 < n < 27). Next line describes n male and n female names. Male name is a lowercase letter, female name is an upper-case letter. Then go n lines, that describe preferable lists for males. Next n lines describe preferable lists for females.
Output
For each test case find and print the pairs of the stable marriage, which is male-optimal. The pairs in each test case must be printed in lexicographical order of their male names as shown in sample output. Output an empty line between test cases.
Sample Input
2 3 a b c A B C a:BAC b:BAC c:ACB A:acb B:bac C:cab 3 a b c A B C a:ABC b:ABC c:BCA A:bac B:acb C:abc
Sample Output
a A b B c C a B b A c C
来自网上某大牛:
稳定婚姻问题(TheStable Marriage Problem)” 大致说的就是100个SSGG和100个PPMM按照自己的喜欢程度给所有异性打分排序。每个帅哥都凭自己好恶给每个MM打分:我最爱a,其次爱b,再次爱c...每个帅哥打的分不同,你最爱的可能是我最讨厌的我最爱的可能是他不甚喜欢的。同样,每个美女也同样给每个帅哥打分。现在需要给他们搭配出100 对新郎新娘,并且要保证所得到是稳定婚姻的搭配。那么,什么是不稳定的婚姻呢?所谓不稳婚姻是说, 比如说有两对夫妇(M1、F1)和(M2、F2),M1的老婆是F1,但他更爱F2;而F2的老公虽说是M2,但她更爱M1——这样的婚姻就是不稳婚姻,M1和F2理应结合,他们现在各自的婚姻都是错误。 那么,我们如何找到一个算法来构造这100个稳定婚姻呢?这个是数学界切切实实研究过的问题。对于以前没有接触过这个问题的人,这个理论最出人意外的结论是: 传统的求爱、结婚过程是male-optimal(男生主动)的,也就是说,男性能够得到尽可能好的心上人,女性却不然。这个问题和图论有关, 最早是由两个美国数学家1962年在American Mathematical Monthly上提出的,相关的参考文献其实很多,下面这个网页大概是讲得最通俗易懂的: "The Stable Marriage Problem" by Harry Mairson,http://www.cs.columbia.edu/~evs/intro/stable/writeup.html 那么,开始激动人心求婚过程啦 第一天上午, 所有的男生都向自己最爱的美眉求婚。下午,每个MM看看自己有没有收到, 收到了多少人的求婚。如果只收到一个男生的求婚,那么就和他订婚。如果收到多于一个GG的求婚,那么就和其中她最爱的那个男人订婚,同时把其他男人都拒掉。如果一个求婚都没有,不要着急,最后总会有的。晚上,检查一遍,如果所有MM都订婚了,OK,万事大吉,明天举行集体婚礼! 但如果还有人没有订婚,那么事情还没有完,第二天还得重复。 第二天上午,所有还没订婚的男生向自己次爱的美眉求婚(因为昨天已经被他们的最爱拒绝了)下午,每个MM再看一遍自己收到订婚的情况。如果她已经订婚了,但是又有一个她更爱的男人来向她求婚,那就把原来那个拒绝掉 ,再和这个更爱的男人订婚;如果还没订婚,那就和第一天的下午的处理一样。晚上再检查一遍,如果还是有人没有订婚,那第三天再重复。
第三天上午,所有没有订婚的GG,包括第一天订了第二天又被踹出来的( 看来要有点忧患意识),再向还没有拒绝过他的MM中他最爱的那个求婚
...... 如此周而复始,直到最后大家都订了婚,便一起结婚!哈哈,恭喜恭喜 这么个过程,数学上可以证明如下性质: 1) 这个过程会中止,也就是说,总有大家都订了婚的一天,不可能无限循环。 2) 中止后所有的婚姻是稳定婚姻。我们能证明的是,通过上面那个求婚过程,所有的婚姻都是稳定的,没有人犯错误。 3) 比较引人注目的是,这个过程是male-optimal(男生主动)的,男性能够获得尽可能好的伴侣,比如说最后有二十个女人拒绝了他,他仍然能够得到剩下的八十个女人中他最爱的那一个。 4) 更有甚者,这个过程是female-pessimal的,女人总是在可能的情况下被最不喜欢的人追上:eek:。这一点没有那么直观的理解,勉强要解释的话,可以这么看:虽说女人每换一次订婚对象,都往上升一层,但起点可能很低,虽说在一步步接近她最爱的目标,但最后往往达不到。比如说还差三十名就达到她最爱的人了,但这时Game Over,所有的人都已订了婚,这样她也只能死了心了!还有三十个她更爱的人还没向她求过婚,可是她也无可奈何了...
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define maxn 30
int a[200];//a[a+i]表示男士a+i的编号为i,a[A+j]表示女士A+j的编号为j
int prefer_male[maxn][maxn],prefer_female[maxn][maxn];//男女士偏好表
int match_female[maxn],match_male[maxn];//记录男女士现任女男友的编号
int lettle[maxn][maxn];//表示女士i今天收到的第j封信的作者编号(即对第i女士表白的第j个男士的标号)
int num_lettle[maxn];//记录第i天的信的数量
int curpoint[maxn];//记录男士下一次表白的女士
int n;
bool finish()//所有男士都有女友结束
{
for(int i=0; i<n; i++)
if(match_male[i]==-1)
return false;
return true;
}
int find_pos(int male,int female)//返回女士对男士的评价值
{
for(int i=0; i<n; i++)
if(male==prefer_female[female][i])
return i;
}
void solve()
{
int i,j;
memset(match_male,-1,sizeof(match_male));
memset(match_female,-1,sizeof(match_female));
memset(curpoint,0,sizeof(curpoint));
while(!finish())
{
memset(num_lettle,0,sizeof(num_lettle));
memset(lettle,-1,sizeof(lettle));
for(i=0; i<n; i++)//男士表白写信
{
if(match_male[i]==-1)
{
lettle[prefer_male[i][curpoint[i]]][num_lettle[prefer_male[i][curpoint[i]]]++]=i;
//prefer_male[i][curpoint[i]表示第i个男士第curpoint[i]个喜欢的女士编号
//num_lettle[prefer_male[i][curpoint[i]]]表示该女士收到信的个数
//整天表示该女士一天收到信的作者编号
curpoint[i]++;
}
}
for(i=0; i<n; i++)//女士看信
{
if(match_female[i]==-1&&num_lettle[i]==1)//只有一个人表白,女士别无选择了
{
match_female[i]=lettle[i][0];
match_male[lettle[i][0]]=i;
}
else if(match_female[i]==-1&&num_lettle[i]>1)//多个人表白,女士要选自己最喜欢的了
{
int favor=lettle[i][0];
for(j=1; j<num_lettle[i]; j++)
{
if(find_pos(lettle[i][j],i)<find_pos(favor,i))
favor=lettle[i][j];
}
match_female[i]=favor;
match_male[favor]=i;
}
else if(match_female[i]!=-1&&num_lettle[i]!=0)//女士已经有男友,但是还是收到表白信,
{ //她会再重新选择自己最喜欢的,现任男友就被甩了,囧啊!
int favor=-1;
for(j=0; j<num_lettle[i]; j++)
{
if(find_pos(lettle[i][j],i)<find_pos(match_female[i],i))
favor=lettle[i][j];
}
if(favor!=-1)
{
match_male[match_female[i]]=-1;//被甩了~~~~
match_female[i]=favor;//新人成对,O(∩_∩)O~
match_male[favor]=i;
}
}
}
}
}
int main()
{
int t;
char temp;
cin>>t;
while(t--)
{
cin>>n;
for(int i=0; i<n; i++)//输入编号
{
cin>>temp;
a[temp]=i;
}
for(int j=0; j<n; j++)
{
cin>>temp;
a[temp]=j;
}
for(int i=0; i<n; i++)//男女士对异性评价值
{
cin>>temp;
int male=temp;
cin>>temp;
for(int j=0; j<n; j++)
{
cin>>temp;
prefer_male[a[male]][j]=a[temp];
}
}
for(int i=0; i<n; i++)
{
cin>>temp;
int female=temp;
cin>>temp;
for(int j=0; j<n; j++)
{
cin>>temp;
prefer_female[a[female]][j]=a[temp];
}
}
solve();
for(int i=0; i<n; i++)//输出,挺有才
for(int j='a'; j<='z'; j++)
{
if(a[j]==i)
{
putchar(j);
putchar(' ');
int index=match_male[i];
for(int k='A'; k<='Z'; k++)
if(a[k]==index)
{
putchar(k);
break;
}
cout<<endl;
break;
}
}
if(t!=0)
cout<<endl;
}
return 0;
}
另附一连接:用(稳定婚姻 Gale-Shapley算法 )