【学习记录】稳定婚姻问题

定义

题意:有 n n n n 女,每一个人都对其他 n n 个异性有不同程度的喜爱,用一个长为 n n 的列表表示,列表中的异性按喜爱程度从高到低排列。问能否找出一个结婚方案,使得不存在两对夫妻 ( m , w ) , ( m , w ) (m, w'), (m', w) ,使得 m m 比起 w w' 更喜爱 w w w w 比起 m m' 更喜爱 m m

如果两对夫妻 ( m , w ) , ( m , w ) (m, w'), (m', w) 没有上述情况就称这两对夫妻是稳定的,否则就是不稳定的

用图论的语言描述,我们要找的结婚方案就是二分图中的一个完美匹配,且要是一个稳定匹配

Gale-Shapley 算法

这是一个符合直觉的算法,直接写成伪代码就能表述意思。

初始化:所有男女都没有对象

WHILE 还有某个男性没有对象,且其尚未追求过所有女性
    选择这样一个男性 m
    设 w 为 m 尚未追求过的,且 m 喜爱程度最高的女性

    IF w 没有对象
        让 (m, w) 暂时结对
    ELSE
        设当前 w 与 m' 是一对
        IF w 比起 m' 更喜欢 m
            让 (m, w) 暂时结对,m' 变为没有对象
        ELSE
            m 被拒绝,仍然没有对象
END

最后所有结对的男女即成夫妻。

算法正确性

  1. 算法是否会终止?

    会,在 n 2 n^2 轮内终止。原因显然。

  2. 算法是否找到完美匹配?

    是,否则必然有一对男女都没有对象,而该男性由于没有对象一定会追求该女性,使得两者结对。

  3. 算法是否找到稳定匹配?

    是,考虑最终结果中任意两对夫妻 ( m , w ) , ( m , w ) (m, w'), (m', w) 。如果 m m 追求过 w w ,那么 w w 比起 m m 更喜爱 m m' ;否则由于男性按照喜爱程度降序选择女性, m m 比起 w w 更喜爱 w w' 。无论哪种情况,这两对夫妻都是稳定的。

算法其他特性

定义女性 w w 是男性 m m 可行对象(valid partner),若存在某个稳定匹配,使得 ( m , w ) (m, w) 是一对夫妻。对女性的男性可行对象定义类似。

定理:无论以何种方式实现算法,算法都只会返回唯一的结果。且该结果满足:

  1. 对任意男性最优:算法给出的其妻子,都是所有可行对象中,他的喜爱程度最的。
  2. 对任意女性最劣:算法给出的其丈夫,都是所有可行对象中,她的喜爱程度最的。

证明:设算法给出的匹配是 S S^* 。我们先证明第一点。

考虑反证。由于男性追求女性是按照喜爱程度降序,因此如果存在男性 m m ,使得其妻子 w w 不是所有可行对象中, m m 的喜爱程度最高的,那么 m m 已经被之前的某个喜爱程度更高的可行对象 w w' 拒绝过了。

不妨假设 m m 是算法执行过程中第一个受到如此待遇的男性。按照定义,存在另一个稳定匹配 S S ,使得 ( m , w ) (m, w') 是一对夫妻。

S S^* 中, w w' 的丈夫是 m m' 。显然 w w 喜爱 m m' 甚于 m m

再设 S S 中, m m' 的妻子为 w w'' 。那么由于之前所设, m m 第一个被更喜爱的可行对象拒绝的男性,那么 m m' 会在 S S^* 中与 w w' 而不是 w w'' 结婚,就只能是因为 m m' 喜爱 w w' 甚于 w w'' 。否则, m m' 会先追求 w w'' ,被拒绝后才会追求 w w' ,而这与之前所设矛盾。

由此可得在 S S 中, ( m , w ) , ( m , w ) (m, w'), (m', w'') 是不稳定的两对夫妻,这与 S S 是稳定匹配相矛盾。

在这里插入图片描述

再证明第二点。假设算法给出的匹配 S S^* 中存在女性 w w ,使得其丈夫 m m 不是所有可行对象中, w w 的喜爱程度最低的,那么存在另一个稳定匹配 S S ,使得 w w 与所有可行对象中喜爱程度最低的 m m' 结对。显然, w w 喜爱 m m' 甚于 m m

m m S S 中的妻子是 w w' 。那么由于男性最优性, m m 喜爱 w w' 甚于 w w 。这导致 ( m , w ) , ( m , w ) (m', w), (m, w') 是不稳定的两对夫妻,这与 S S 是稳定匹配相矛盾。

在这里插入图片描述

代码实现

UVa 1175 为例,实现这一算法。时间复杂度为 O ( n 2 ) O(n^2)

int n, pref[1005][1005], rnk[1005][1005];
// 分别为男对女的喜爱值列表,女对男的喜爱值排名(降序)
int cur[1005], wife[1005], husband[1005];
// 当前追求到哪一个
queue<int> q;
// 用队列辅助求解
void GS(){
    memset(wife, 0, sizeof(wife));
    memset(husband, 0, sizeof(husband));
    for (int i = 1; i <= n; ++i)
        cur[i] = 1, q.push(i);
    while (!q.empty()){
        int h = q.front();
        q.pop();
        int targ = pref[h][cur[h]++];
        if (!husband[targ] || rnk[targ][h] < rnk[targ][husband[targ]]){
            wife[h] = targ;
            if (husband[targ] > 0){
                wife[husband[targ]] = 0;
                q.push(husband[targ]);
            }
            husband[targ] = h;
        } else if (cur[h] <= n){
            q.push(h);
        }
    }
    for (int i = 1; i <= n; ++i)
        printf("%d\n", wife[i]);
}

参考资料

  • 《Algorithm Design》

猜你喜欢

转载自blog.csdn.net/zqy1018/article/details/108508887