poj3487 & hdu1914 The Stable Marriage Problem 稳定婚姻系统

来源:互联网 发布:小学生杀手软件 编辑:程序博客网 时间:2024/05/14 22:49
//n个男生,n个女生配对//n个男生在心中对每个女生有个排名//n个女生在心中对每个男生有个排名//问怎样配对使得所有人都配对好且不存在两对婚姻中存在//A和a结婚,B和b结婚,但是A更偏爱b而非a而且b也更偏爱A而非B//这样A和b可能会私奔//①这里用的是Gale-Shapley算法//每一位单身男在所有尚未拒绝她的女士中选择一位被他排名最优先的女士;//②每一位女士将正在追求她的单身男与其当前男友进行比较,选择其中排名优//先的男士作为其男友,即若单身男优于当前男友,则抛弃前男友;否则保留其男友,拒绝单身男。//③若某男士被其女友抛弃,重新变成单身男。#include<cstdio>#include<cstring>#include<iostream>using namespace std ;const int maxn = 100 ;bool single[maxn] ; //该男生是否单身int  F[maxn][maxn] ;int  match[maxn] ;   //match[i]存入第i个女生配对的男生的编号int num[maxn] ;   //存入第i个男生追到第几个女生int pos[maxn][maxn] ;char str[maxn] ;int id[maxn] ;int idm[maxn] ;char s[maxn] ; int n ;int marri[maxn] ; //marri[i] 存入第i个男生和其结婚的女生的编号int main(){    //freopen("in.txt" ,"r" , stdin) ;    int T;    int cas = 0 ;    scanf("%d" , &T) ;    while(T--)    {       scanf("%d" ,&n) ;       memset(match , -1 , sizeof(match)) ;       memset(id , 0 ,sizeof(id)) ;       memset(idm , 0 , sizeof(idm)) ;       for(int i = 1;i <= n;i++)       single[i] = true ,num[i] = 1;       char ch[10] ;       for(int i = 1;i <= 2*n;i++)       {           scanf("%s" ,  ch) ;           str[i] = ch[0] ;           if(i <= n)           id[str[i]-'a'] = i ;//存入每个男生对应字母的编号           else           idm[str[i]-'A'] = i - n;//存入每个女生对应字母的编号       }       for(int i = 1;i <= 2*n ; i++)       {           scanf("%s" , s) ;           for(int j = 1;j <= n;j++)              if(i <= n)                 F[id[s[0]-'a']][j] = idm[s[j+1]-'A'];//F[i][j]存入编号为i的男生的第j个喜欢的女生的编号              else                  pos[idm[s[0]-'A']][id[s[j+1]-'a']] = j ;//p[i][j]存入第j个男生在第i个女生排第几位       }          while(1)       {           int flag = 0 ;           for(int i = 1;i <= n;i++)           {               if(!single[i])continue ;                int m = F[i][num[i]] ;  //第i个男生现在要追的女生                if(match[m] == -1)      //如果这个女生还没配对,他两直接配对                {                    single[i] = false ;                      match[m] = i ;                }                else                {                    if(pos[m][match[m]] > pos[m][i])//如果现在要追这个女生的男生在这个女生心中的位置在她已经配对的男生前面                    {                               //那么就甩掉和其配对的男生,和现在这个男生结合                        single[i] = false ;       //现在的男生脱单                        single[match[m]] = true ;//那个女生的前男友重返单身                        num[match[m]]++;        //女生前男友不得不去追求下一个女生                        match[m] = i ;                    }                    else num[i]++ ;          //否则这个男生去追下一个                    flag = 1 ;           //这样一定有一个男生没脱单,只得再继续配对                }            }            if(!flag)            break;       }       for(int i = 1;i <= n;i++)       marri[match[i]] = i ;       if(cas)       puts("") ;       for(int i = 0;i <= 26;i++)       if(id[i])       printf("%c %c\n" , i + 'a' , str[marri[id[i]]+n]) ;       cas = 1;    }}
0 0
原创粉丝点击