hdu 1522 稳定婚姻问题 propose-reject

Marriage is Stable

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 438    Accepted Submission(s): 257
Special Judge


Problem Description
Albert, Brad, Chuck are happy bachelors who are in love with Laura, Marcy, Nancy. They all have three choices. But in fact, they do have some preference in mind. Say Albert, he likes Laura best, but that doesn't necesarily mean Laura likes him. Laura likes Chuck more than Albert. So if Albert can't marry Laura, he thinks Nancy a sensible choice. For Albert, he orders the girls Laura > Nancy > Marcy.

For the boys:

Albert: Laura > Nancy > Marcy
Brad: Marcy > Nancy > Laura
Chuck: Laura > Marcy > Nancy

For the girls:

Laura: Chuck > Albert > Brad
Marcy: Albert > Chuck > Brad
Nancy: Brad > Albert > Chuck

But if they were matched randomly, such as

Albert <-> Laura
Brad <-> Marcy
Chuck <-> Nancy

they would soon discover it's not a nice solution. For Laura, she likes Chuck instead of Albert. And what's more, Chuck likes Laura better than Nancy. So Laura and Chuck are likely to come together, leaving poor Albert and Nancy.

Now it's your turn to find a stable marriage. A stable marriage means for any boy G and girl M, with their choice m[G] and m[M], it will not happen that rank(G, M) < rank(G, m[G])and rank(M, G) < rank(M, m[M]).
 
Input
Each case starts with an integer n (1 <= n <= 500), the number of matches to make.

The following n lines contain n + 1 names each, the first being name of the boy, and rest being the rank of the girls.

The following n lines are the same information for the girls.

Process to the end of file.
 
Output
If there is a stable marriage, print n lines with two names on each line. You can choose any one if there are multiple solution. Print "Impossible" otherwise.

Print a blank line after each test.
 
Sample Input
3 Albert Laura Nancy Marcy Brad Marcy Nancy Laura Chuck Laura Marcy Nancy Laura Chuck Albert Brad Marcy Albert Chuck Brad Nancy Brad Albert Chuck
 
Sample Output
Albert Nancy Brad Marcy Chuck Laura
 
Author
CHENG, Long
 
Source
 
Recommend
8600
 
stable marriage problem, 用 Gale-Shapley Algorithm,  即
 Propose-and-reject algorithm  求婚-拒绝算法  ,即每次单身汉按喜欢程度递减的顺序向女士表白,女士根据自己的喜欢偏好选择汉子,最终得到稳定的男女配对。
简单说明,
1.假设男士A最终与B配对,C与D配对,但A相对B更喜欢D,则A肯定被D拒绝过,且D相对A更喜欢C,所以B是A可得且喜欢程度最高的妹子;
2.假设girl B 相对A更喜欢C, 则C未向B表白过,否则就拒绝/抛弃B了,再综合考虑向B表白过的汉子,A是她的最佳选择,这么看来配对比较稳定。。。
AC代码:(详细注释。。。)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<queue>

using namespace std;

#define LL long long
#define ULL unsigned long long
#define UINT unsigned int
#define MAX_INT 0x7fffffff
#define MAX_LL 0x7fffffffffffffff
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))

#define MAXN 555
int pref[MAXN][MAXN], fb[MAXN], fw[MAXN];
queue<int> q;                           //光棍队列
map<string, int> m;
string manname[MAXN], womanname[MAXN];

int cntman, cntwoman, nxt[MAXN];        //man数量,woman数量,下一个最喜欢的人
int order[MAXN][MAXN], n;
const int male=0, female=1;

int ID(string s, int &cnt){         //hash 字符串到数字
    return (m.count(s) ? m[s] : m[s]=cnt++);
}

void engage(int man, int woman){
    int m=fb[woman];
    if(m) q.push(m), fw[m]=0;           //如果有未婚夫,抛弃
    fw[man]=woman;
    fb[woman]=man;
}

void solve(){
    memset(fw, 0, sizeof(fw));
    memset(fb, 0, sizeof(fb));
    while(!q.empty()){
        int man=q.front();      q.pop();
        int woman=pref[man][nxt[man]++];
        if(!fb[woman]) engage(man, woman);          //没有未婚夫
        else if(order[woman][fb[woman]]>order[woman][man]) engage(man, woman);   //出现更迷人的汉子
        else q.push(man);
    }
    for(int i=1; i<=n; i++) cout<<manname[i]<<' '<<womanname[fw[i]]<<endl;
}
                                                        //test是个debug函数
void test(){
    for(int i=1; i<cntman; i++){
        cout<<"man "<<i<<":	";
        cout<<manname[i]<<'	';
        cout<<(m.count(manname[i]))<<endl;
    }
    cout<<"woman:"<<endl;

    for(int i=1; i<cntwoman; i++){
        cout<<"woman "<<i<<":	";
        cout<<womanname[i]<<'	';
        cout<<(m.count(womanname[i]))<<endl;
    }
}

int main(){
    //freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
    while(cin>>n){          getchar();
        int i,j;
        m.clear();      cntman=1;       cntwoman=1;
        string s;       char ch;
        for(i=1; i<=n; i++){
            getline(cin, s, ' ');      int k=ID(s, cntman);     //hash汉子名字到编号,易处理
            manname[k]=s;
            for(j=1; j<=n; j++){
                ch=(j==n ? '
' : ' ');
                getline(cin, s, ch);
                pref[k][j]=ID(s, cntwoman);             //汉子k第j喜欢的妹子为ID(...)
            }
            q.push(k);
            nxt[k]=1;
        }

        for(i=1; i<=n; i++){
            getline(cin, s, ' ');       int k=ID(s, cntwoman);
            womanname[k]=s;
            for(j=1; j<=n; j++){
                ch=(j==n ? '
' : ' ');
                getline(cin, s, ch);
                int t=ID(s, cntman);
                order[k][t]=j;                      //妹子k第j喜欢的汉子是t
            }
        }
        if(cntman == cntwoman) solve();             //这里会存在光棍/剩女的可能
        else cout<<"Impossible"<<endl;
//        test();
        cout<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ramanujan/p/3320659.html