这篇解释得比较好: 点击打开链接
稳定婚姻问题:实际上就是n男n女,每个人都对其他异性有一个喜欢值,給他们匹配,然后最后得到他们关系比较稳定的一种方法。其中要使得关系稳定,要满足的条件是两个人中任何一个人都认为自己的配偶是喜欢自己的人中最好,这样如果一个想出轨,一定不会找比自己现任差的,可是比自己现任好的又不会喜欢他,因为人家认为人家的现任要比他好。所以婚姻稳定。
算法:简单说就是,男士不停向女士求爱,女士不停拒绝。对每个男士喜欢的女士按照他喜欢的的程度有深到浅排序,然后每个男就按照这个顺序想女士求爱,首先是最喜欢的,然后是次喜欢的,and so on。然后女士如果是单身,她就会接受向她求爱的男士,如果不是单身,她就比较向他求爱的男士和她的现任选择她更喜欢的,然后她比较不喜欢的男士变成单身。直达所有男士都找到了他的另一半,算法结束,此时就是稳定的。因为男士每次都按照喜欢的顺序想女士求爱,所以只要不被女士拒绝,这个女士就是他最好的选择,如果他的现任更喜欢向他求婚爱的其他男士,那么这个女士就会抛弃他,他接着向下一个求爱, 也就是说一旦男士向一位女士求爱, 不管女士在他心中什么位置,这个男士心中比她还好的女士都不喜欢这个男士,保证了男士不出轨,并且按照顺序她就是男士能选择的女士中最喜欢的。而对于女士,每次选择的男士都是向她求爱的人中她比较喜欢的,这样一来,男士可以分成两种,一种是没有向她求爱的,说明这个男士有更喜欢的女士,而且他喜欢的女士也喜欢他,所以对于当前的女士与这个她喜欢的男士白头偕老不可能;第二种是向女士求爱的男士,因为女士择优原则,所以肯定是选了向她求爱的人中她最喜欢!综上,婚姻稳定!
代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cctype>
using namespace std;
const int N = 30;
int pref[N][N], order[N][N], future_h[N], future_w[N], next[N]; //pref[i][j]第i个男士第j喜欢的女士的标号,order[i][j]是第i个女士对第j个男士喜欢的程度
char h[N], w[N], ss[50];
int rh[N*5], rw[N*5];
struct Node {
char name;
char fname;
int w;
}ans[N];
int T, n;
queue<int>q;
bool cmp( Node a, Node b ) { return a.name < b.name; }
void engage( int man, int woman )
{
//printf("man:%d woman:%d\n", man, woman);
int m = future_h[woman];
if ( m ) {
future_w[man] = 0;
q.push(m);
}
future_h[woman] = man;
future_w[man] = woman;
ans[man].w = woman;
ans[man].fname = w[woman];
//printf("f_h[%d] %d f_w[%d] %d\n", woman, future_h[woman], man, future_w[man]);
}
int main()
{
scanf("%d", &T);
while ( T-- ){
scanf("%d", &n);
getchar();
char tmp;
for ( int i = 1; i <= n; ) {
scanf("%c", &tmp);
if ( islower(tmp) ) {
ans[i].name = tmp;
h[i] = tmp;
rh[tmp] = i++;
}
}
for ( int i = 1; i <= n; ) {
scanf("%c", &tmp);
if ( isupper(tmp)) {
w[i] = tmp;
rw[tmp] = i++;
}
}
getchar();
//for ( int i = 1; i <= n; ++i ) printf("%c %d\n", h[i], rh[h[i]]);
//for ( int i = 1; i <= n; ++i ) printf("%c %d\n", w[i], rw[w[i]]);
for ( int i = 1; i <= n; ++i ) {
scanf("%s", &ss);
//printf("%s\n", ss);
int u = rh[ss[0]];
for ( int j = 2; j < strlen(ss); ++j ) {
int v = rw[ss[j]];
pref[u][j-1] = v;
}
next[u] = 1;
future_w[u] = 0;
q.push(u);
//getchar();
}
//for ( int i = 1; i <= n; ++i, printf("\n")) for ( int j = 1; j <= n; ++j ) printf("%d ", pref[i][j]);
for ( int i = 1; i <= n; ++i ) {
scanf("%s", ss);
int u = rw[ss[0]];
for ( int j = 2; j < strlen(ss); ++j ) {
int v = rh[ss[j]];
//printf("%c v %d\n", ss[j], v);
order[u][v] = j-1;
}
future_h[u] =0;
}
//for ( int i = 1; i <= n; ++i, printf("\n")) for ( int j = 1; j <= n; ++j ) printf("%d ", order[i][j]);
while ( !q.empty() ) {
int man = q.front(); q.pop();
int woman = pref[man][next[man]++];
//printf("%d %d %d\n", woman, future_h[woman], man );
if ( !future_h[woman] ) engage( man, woman );
else if ( order[woman][man] < order[woman][future_h[woman]] ) engage( man, woman );
else q.push( man );
}
//sort( ans+1, ans+1+n, cmp);
for ( int i = 1; i <= n; ++i ) printf("%c %c\n", ans[i].name, ans[i].fname);
if ( T ) printf("\n");
// printf("ok\n");
}
}