poj 3487

来源:互联网 发布:手机截图软件下载 编辑:程序博客网 时间:2024/05/23 14:43
The Stable Marriage Problem
Time Limit: 1000MS Memory Limit: 65536KTotal 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 thatf ∈ F prefers m ∈ M to her current partner andm prefersf 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

23a b c A B Ca:BACb:BACc:ACBA:acbB:bacC:cab3a b c A B Ca:ABCb:ABCc:BCAA:bacB:acbC:abc

Sample Output

a Ab Bc Ca Bb Ac C
 
来自网上某大牛:
稳定婚姻问题(The Stable 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再看一遍自己收到订婚的情况。如果她已经订婚了,但是又有一个她更爱的男人来向她求婚,那就把原来那个拒绝掉POJ <wbr>3487 <wbr>稳定婚姻,再和这个更爱的男人订婚;如果还没订婚,那就和第一天的下午的处理一样。晚上再检查一遍,如果还是有人没有订婚,那第三天再重复。 第三天上午,所有没有订婚的GG,包括第一天订了第二天又被踹出来的(POJ <wbr>3487 <wbr>稳定婚姻看来要有点忧患意识),再向还没有拒绝过他的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 30int a[200];//a[a+i]表示男士a+i的编号为i,a[A+j]表示女士A+j的编号为jint 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算法 )
 
原创粉丝点击