hdu 1522

这题是一个匹配问题,一开始想用km做最佳匹配,但是图很大肯定会tle,思考无果后只能去搜搜题解,这是个经典问题吧。从http://www.cnblogs.com/drizzlecrj/archive/2008/09/12/1290176.html这里找到了相应的资料。

稳定婚姻是组合数学里面的一个问题。

问题大概是这样:有一个社团里有n个女生和n个男生,每位女生按照她的偏爱程度将男生排序,同时每位男生也按照自己的偏爱程度将女生排序。然后将这n个女生和n个男生配成完备婚姻。

如果存在两位女生A和B,两位男生a和b,使得A和a结婚,B和b结婚,但是A更偏爱b而不是a,b更偏爱A而不是B,则这个婚姻就是不稳定的,A和b可能背着别人相伴而走,因为他俩都认为,与当前配偶比起来他们更偏爱各自的新伴侣。

如果完备婚姻不是不稳定的,则称其是稳定的。通过证明,可以得到每一个n女n男的社团,都存在稳定婚姻的结论。但是这种情况只在异性的社团中存在。也就是说在同性的社团里面,稳定婚姻的存在性将不再被保证。

Gale-Shapley 算法

while  存在男人m是自由的且还没对每个女人都求过婚
      选择这个男人m
                令w是m的优先表中还没求过婚的最高排名的女人
        if  w是自由的  
            (m,w)变成约会状态
        else  w当前与m1约会
              if  w更偏爱m1而不爱m
                                  m保持自由
              else    w更偏爱m而不爱m1
                                        (m,w)变成约会状态
                    m1变成自由
              endif
                  endif
endwhile

是不是感觉很简单,用很常理的方法写的算法。

Run IDSubmit TimeJudge StatusPro.IDExe.TimeExe.MemoryCode Len.LanguageAuthor
54269602012-02-27 23:36:05Accepted15220MS568K1851 BG++xym2010

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
int n,gp_boy[505][505],gp_girl[505][505],boy[505],girl[505],rank[505];
map<string,int>mp_boy,mp_girl;
string sboy[505],sgirl[505];
char s[1000];
void deal()
{
    memset(boy,0,sizeof(boy));
    memset(girl,0,sizeof(girl));
    for(int i=1;i<=n;i++)rank[i]=1;
    while(1)
    {
        int flag=0;
        for(int i=1;i<=n;i++)
        {
            if(!boy[i])
            {
                int g=gp_boy[i][rank[i]++];
                if(!girl[g])
                    boy[i]=g,girl[g]=i;
                else if(gp_girl[g][i]>gp_girl[g][girl[g]])
                        boy[girl[g]]=0,girl[g]=i,boy[i]=g;
                flag=1;
            }
        }
        if(!flag)break;
    }
    for(int i=1;i<=n;i++)
    {
        cout<<sboy[i]<<' '<<sgirl[boy[i]]<<endl;
    }
    puts("");
}
int main()
{
    while(~scanf("%d",&n))
    {
        getchar();
        mp_boy.clear(),mp_girl.clear();
        int pos=1,tem;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s);
                sboy[i]=s,mp_boy[s]=i;
                for(int j=1;j<=n;j++)
                {
                    scanf("%s",s);
                    tem=mp_girl[s];
                    if(tem==0)
                    mp_girl[s]=tem=pos++,sgirl[tem]=s;
                    gp_boy[i][j]=tem;
                }
        }
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            int x=mp_girl[s];
            for(int j=0;j<n;j++)
            {
                scanf("%s",s);
                int y=mp_boy[s];
                gp_girl[x][y]=n-j;
            }
        }
        deal();
    }
    return 0;
}
发现vim贴的代码会带颜色。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值