The Stable Marriage Problem(稳定婚姻问题)

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 t he 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 and m 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


题意:“稳定婚姻问题”在生活中是一个典型的问题,通俗地可叙述为:当前有N位男生和N位女生最后要组成稳定的婚姻家庭,过程开始之前男生和女生在各自的心目中都按照喜爱程度对N位异性有了各自的排序.然后开始选择自己的对象。

分析:先对所有男士进行落选标记,称其为自由男。当存在自由男时,进行以下操作: 

① 每一位自由男在所有尚未拒绝她的女士中选择一位被他排名最优先的女士; 

② 每一位女士将正在追求她的自由男与其当前男友进行比较,选择其中排名优先的男士作为其男友,即若自由男优于当前男友,则抛弃前男友;否则保留其男友,拒绝自由男。 

③ 若某男士被其女友抛弃,重新变成自由男。

自由男们主动出击,依次对最喜欢和次喜欢的女人求爱,一旦被接受,即失去自由身,进入订婚状态;而女人们则采取“守株待兔”和“喜新厌旧”策略,对前来求爱的男士进行选择:若该男子比未婚夫强,则悔婚,选择新的未婚夫;否则拒绝该男子的求婚。被女友抛弃的男人重获自由身,重新拥有了追求女人的权利——当然,新的追求对象比不过前女友。 

代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
struct people
{
    char na;//本人名
    char lo[27];//有好感的序列
    bool use;//是否有伴侣
    char ma;//伴侣名
};
int n,m,i,j,cnt;
people M[27],F[27];
bool judge()
{
    for(i=0;i<m;i++)
        if(!F[i].use)
            return false;
    return true;
}
bool F_change(int t,int k)
{
    for(int p=0;p<m;p++)
    {
        if(F[t].lo[p]==F[t].ma)
            return false;
        if(F[t].lo[p]==M[k].na)
            return true;
    }
}
int M_num(int t)
{
    for(int p=0;p<m;p++)
        if(M[p].na==F[t].ma)
            return p;
}
int F_num(char c)
{
    for(int p=0;p<m;p++)
        if(F[p].na==c)
            return p;
}
int main()
{
    //freopen("h.in","r",stdin);
    //freopen("hh.out","w",stdout);
    cnt=0;
    scanf("%d",&n);
    while(n--)
    {
        if(cnt)
            printf("\n");
        cnt=1;
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            M[i].use=false;
            F[i].use=false;
            cin>>M[i].na;
        }
        for(i=0;i<m;i++)
            cin>>F[i].na;
        char temp[30];
        for(i=0;i<m;i++)
        {
            scanf("%s",&temp);
            strcpy(M[i].lo,temp+2);
        }
        for(i=0;i<m;i++)
        {
            scanf("%s",&temp);
            strcpy(F[i].lo,temp+2);
        }
        while(!judge())
        {
            for(i=0;i<m;i++)
            {
                if(!M[i].use)
                {
                    for(j=0;j<m;j++)
                    {
                        int num=F_num(M[i].lo[j]);
                        if(!F[num].use)
                        {
                            F[num].ma=M[i].na;
                            M[i].use=true;
                            F[num].use=true;
                            M[i].ma=F[num].na;
                            break;
                        }
                        else
                        {
                            if(F_change(num,i))
                            {
                                M[M_num(num)].use=false;
                                F[num].ma=M[i].na;
                                M[i].use=true;
                                M[i].ma=F[num].na;
                                break;
                            }
                        }
                    }
                }
            }
        }
        for(i=0;i<m;i++)
            printf("%c %c\n",M[i].na,M[i].ma);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值