poj 3487(图论 稳定婚姻)

题目链接:http://poj.org/problem?id=3487

题目意思:“稳定婚姻问题”在生活中是一个典型的问题,通俗地可叙述为:当前有N位男生和N位女生最后要组成稳定的婚姻家庭,过程开始之前男生和女生在各自的心目中都按照喜爱程度对N位异性有了各自的排序.然后开始选择自己的对象,其规则是:男生第一天均向各自最喜欢的女生写一封“情书”。(来自百度百科)

 

算法思路(Gale-Shapley算法):

先对所有男士进行落选标记,称其为自由男。当存在自由男时,进行以下操作:
①每一位自由男在所有尚未拒绝她的女士中选择一位被他排名最优先的女士;
②每一位女士将正在追求她的自由男与其当前男友进行比较,选择其中排名优先的男士作为其男友,即若自由男优于当前男友,则抛弃前男友;否则保留其男友,拒绝自由男。
③若某男士被其女友抛弃,重新变成自由男。
 
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define inf 0x3f3f3f3f
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
int man[40],pref[40][40],order[40][40];
int next[40],future_wife[40],future_huaband[40]; 
int n;
queue<int> q; 

void match(int man,int woman)//匹配 
{
    int m=future_huaband[woman];//女生的现任丈夫,为0则是情况一,非0则是情况二 
    if(m)//有丈夫,则是由情况二传来,先离婚,即清除记录。 
    {
        future_wife[m]=0;
        q.push(m);//该离婚男生继续入对,寻找    
    }    
    future_huaband[woman]=man; 
    future_wife[man]=woman;
}

int main()
{
    std::ios::sync_with_stdio(false);
    int t;
    char c;
    string s;
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(man,0,sizeof(man)); 
        for(int i=0;i<n;i++)
        {
            cin>>c;
            man[c-'a'+1]=1;//标记字母(男生)出现 
        }
        for(int i=0;i<n;i++)
            cin>>c;
        for(int i=0;i<n;i++)
        {
            cin>>s;
            int temp=s[0]-'a'+1;
            for(int j=2;s[j];j++)
                pref[temp][j-1]=s[j]-'A'+1;//记录男生排名中喜欢的女生 
            next[temp]=1;//初始化男生现在追求排名第几的女生 
            future_wife[temp]=0;
            q.push(temp);//将所有男生入队列    
        }
        for(int i=0;i<n;i++)
        {
            cin>>s;
            int temp=s[0]-'A'+1;
            for(int j=2;s[j];j++)
                order[temp][s[j]-'a'+1]=j-1;//记录女生排对该男生的排名 
            future_huaband[temp]=0;
        }
        while(!q.empty())
        {
            int man=q.front();
            q.pop();
            int woman=pref[man][next[man]++];//选取该男生未尝试求婚中排名最前的女生 
            if(!future_huaband[woman])//情况一:该女生没有男生追,直接匹配 
                match(man,woman);
            else if(order[woman][man]<order[woman][future_huaband[woman]])
            //情况二:该女生现在的丈夫排名没有该男生高,匹配 
                match(man,woman);
            else//该女生匹配不了,继续入队,表白排名后面的女生 
                q.push(man);
        }
        for(int i=1;i<40;i++)
            if(man[i])
                cout<<(char)(i-1+'a')<<' '<<(char)(future_wife[i]+'A'-1)<<endl;
        if(t)
            cout<<endl;
    }
    return 0;
}

 

posted @ 2019-04-02 21:15  怀揣少年梦.#  阅读(633)  评论(0编辑  收藏  举报