LOADING

加载过慢请开启缓存 浏览器默认开启

匹配问题

匹配/对集问题

定义


翻译成人话就是,匹配要求边集中任何两条边不相邻,最大匹配要求边数最多,完全匹配要求所有顶点都包含。

霍尔婚姻定理 HALL’S MARRIAGE THEOREM

稳定匹配问题

问题描述:给出一个\(n\)个男性的集合\(M\)\(n\)个女性的集合\(W\),找到一个“稳定”匹配。

每位男性根据对女性的心仪程度从高至低进行排名;
每位女性根据对男性的心仪程度从高至低进行排名;

不稳定对:给出一个完美匹配\(S\),男性\(m\)和女性\(w\)是不稳定的,如果同时满足下列条件:

\(m\)相比起当前配偶,更喜欢\(w\)
\(w\)相比起当前配偶,更喜欢\(m\)

稳定匹配:一个不包含不稳定对的完美匹配。

Gale-Shapley 算法(延迟决定法)

#include<iostream>
using namespace std;
const int N = 10005;
int M[N] = {0}, W[N] = {0}; // 第0个元素表示已经配对的男性/女性个数;男性和女性集合,0表示目前还单身,>0表示已经和该数字对应的异性配对
int M_pri[N][N] = {0}, W_pri[N][N] = {0}; // 第0个元素记录的是男生 m 在寻找心仪女生时的进度;男性和女性对异性的心仪程度排名

void getPri(int n);
void G_S(int num);
void output(int num);
bool lovemore(int m,int w,int num);

// 获取心仪程度输入
void getPri(int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> M_pri[i][j]; // 表示第i位男性对女性心仪程度排名,M_pri[i][j]位女生排名第j名;
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> W_pri[i][j]; // 表示第i位女性对男性心仪程度排名,W_pri[i][j]位男生排名第j名;
        }
    }
}

// Gale-Shapley 算法
void G_S(int num) {
    int m, w;
    while (M[0] != num) // 男生们还未完成配对
    {
        w = m = 0;
        while (M[++m] != 0) ; // 找到第一个出现的还没有配对的男生m
        w = M_pri[m][++M_pri[m][0]]; // 找到第m位男生心中剩下排名第一的女生w
        if (W[w])   //如果女生已经在约会了
        {
            if (lovemore(m,w,num)) // 如果w更爱m
            {
                M[W[w]] = 0; // w 甩了当前和她配对的
                M[m] = w;
                W[w] = m;   
            }
            else 
                continue;
        }
        else // 如果女生没有约会还是自由状态,成功配对
        {
            M[m]=w;
            M[0]++;
            W[w]=m;
            W[0]++;
        }
    }
}

// 判断w是不是更爱m
bool lovemore(int m,int w,int num) {
    for (int i = 0; i < num; i++) { // 按排名从高到低往下找
        if (W_pri[w][i] == W[w]) { // 先找到和w配对的那个
            return false;
        }
        if (W_pri[w][i] == m) { // 先找到m,说明更爱m
            return true;
        }
    }
}

void output(int num) {
    for (int i = 1;i <= num; i++)
        cout<<"("<<i<<", "<<M[i]<<")"<<endl;
}

void solve() {
    int n;
    cin>>n;
    getPri(n);
    G_S(n);
    output(n);
}

int main() {
    solve();
    return 0;
}