图论:Gale-Shapley算法

Gale-Shapley算法又叫做延迟认可算法,它可以解决这么一个问题

一共有N位男士和N位女士

每位男士对每位女士都有一个好感度,让他们结合成为N对夫妻,要求男士优先表白,最后问结合情况

第一轮,每个男人都选择自己名单上排在首位的女人,并向她表白。
这种时候会出现两种情况:
(1)该女士还没有被男生追求过,则该女士接受该男生的请求。
(2)若该女生已经接受过其他男生的追求,那么该女生会将该男士与她的现任男友进行比较,若更喜欢她的男友,那么拒绝这个人的追求,否则,抛弃现任……
第一轮结束后,有些男人已经有女朋友了,有些男人仍然是单身。
在第二轮追女行动中,每个单身男都从所有还没拒绝过他的女孩中选出自己最中意的那一个,并向她表白,不管她现在是否是单身。
这种时候还是会遇到上面所说的两种情况,还是同样的解决方案。直到所有人都不在是单身。

以上给出了算法的描述,下面直接给出代码,题目是POJ3487

由于这个问题没有太大变式直接套模板就好了,如果要求女士优先,那就把男女身份互换然后再套用这个模板就好了

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<queue> 
 5 using namespace std;
 6 const int maxn=35;
 7 int n;
 8 int ml[maxn][maxn],fl[maxn][maxn],mc[maxn],fc[maxn];
 9 int mn[maxn],fn[maxn];
10 queue<int> q;  //没有配对的男士 
11 int main()
12 {
13     int T;
14     char s[maxn];
15     scanf("%d",&T);
16     while(T--)
17     {
18         scanf("%d",&n);
19         //读入男士的名字,初始化都没有配对 
20         for(int i=0;i<n;i++)
21         {
22             scanf("%s",s);
23             mn[i]=s[0]-'a';
24             q.push(mn[i]);
25         }
26         //将名字排序 
27         sort(mn,mn+n);
28         for(int i=0;i<n;i++)
29         {
30             scanf("%s",s);
31             fn[i]=s[0]-'A';
32         }
33         //男士对女士的印象 
34         for(int i=0;i<n;i++)
35         {
36             scanf("%s",s);
37             for(int j=0;j<n;j++)
38                 ml[i][j]=s[j+2]-'A';
39         }
40         //女士对男士的打分,n号为初始对象 
41         for(int i=0;i<n;i++)
42         {
43             scanf("%s",s);
44             for(int j=0;j<n;j++)
45                 fl[i][s[j+2]-'a']=n-j;
46             fl[i][n]=0;
47         }
48         //一开始男士的期望都是最喜欢的女士 
49         memset(mc,0,sizeof(mc));
50         //女士先初始化一个对象 
51         for(int i=0;i<n;i++)
52             fc[i]=n;
53             while(!q.empty())
54             {
55                 //h=h%maxn+1;
56                 //找出一个没有配对的男士 
57                 int m=q.front();
58                 //男士心怡的女士 
59                 int fm=ml[m][mc[m]];
60                 //如果当前男士比原来的男友好 
61                 if(fl[fm][m]>fl[fm][fc[fm]])
62                 {
63                     //脱单 
64                     q.pop();
65                     //否则考虑下一个对象 
66                     if(fc[fm]!=n)
67                     {
68                         q.push(fc[fm]);
69                         mc[fc[fm]]++;
70                     }
71                     //当前男友为这位男士 
72                     fc[fm]=m;
73                 }
74                 else mc[m]++;  //如果女士拒绝,考虑下一个对象 
75             }
76             for(int i=0;i<n;i++)
77                 printf("%c %c\n",mn[i]+'a',ml[mn[i]][mc[mn[i]]]+'A');
78             if(T) puts("");
79     }
80     return 0;
81 }

另外记住一点如果队列不是特别正常的队列不要手写,还是STL比较稳

posted @ 2018-08-09 11:24  静听风吟。  阅读(2799)  评论(0编辑  收藏  举报