zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    miniport hook ethFilterDprIndicateReceivePacket 接收拦截时包处理问题
    XRename(文件文件夹超级重命名工具)简介
    正则表达式测试工具
    很好看的表格样式
    FillForms 1.2.9 preliminarily reviewed
    CSDN分页ID提取工具(vb编写)
    html表格样式等整理
    备忘录
    巧用正则巅峰采集黄金白银大盘价信息
    2011年个人奋斗目标
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3320659.html
Copyright © 2011-2022 走看看