Marriage is Stable 【HDU - 1522】【稳定婚姻匹配问题】

题目链接


  什么是婚姻匹配问题呢?我做了这道题后就有了这样的体会 —— 比谁更渣???

  我们知道,有N个男生还有N个女生,要把每个男生和女生匹配起来,让他们结婚,但是呢,有这样的情况,就是假如我们现在B1和G1结婚了,但是呢G1比较B1更喜欢B2,并且B2现在还没有考虑别的女生,B2现在考虑到了G1,那这时候G1这个女孩纸会怎么办呢?甩了B1,跟B2走了!!!天呐,但是没错,稳定婚姻匹配问题就是这么的真实。

  在这里,婚姻稳定的定义:如果男孩i和女孩a牵手,但男孩i对女孩b更喜欢,而女孩b的男朋友j拼不过男孩i,则没有力量阻碍男孩i和女孩b的私奔,这即是不稳定的。

  同样的,我们也可以把婚姻稳定的问题这样阐述(也就是我代码里写的内容了):男孩先去找自己最喜欢的女孩,但是呢,如果这个女孩会被其他的男孩纸选到,并且这个女孩更爱那个后来的男孩纸,女孩就会跟她更爱的男生走了。然后先来的那个男孩子就失恋了,就哭了,他就要去找他的下一个喜欢的女孩纸(情感恢复的真快),然后看看能不能领导落单的她,或者比她现在的男朋友对这个女孩纸而言更man一点?

  那么,最后的结果就会使得,女孩越换越能换到自己更喜欢的男孩纸,男孩纸也不会担心自己的女朋友跟别的男孩纸跑了,因为假如这个女孩纸有更喜欢的男孩纸,那么她更喜欢的男孩纸她一定选不了,是因为那些男孩纸也选择了自己更喜欢的女孩了。

  这个问题证明了,如果有更喜欢的TA,如果想挖墙角的话,只有TA被TA更喜欢的TA带走才行

上面那句话挺绕的,但是就是这样的一个过程,前面的拿到Tarjan,很好的阐述了这道题不可能发生的那种情况。

  所以TA带不走你,要么是你对比现在的对象更不喜欢TA,或者是TA其实不是那样的喜欢你。

  所以,有一句话说的很对,一切都是上天最好的安排。

My Code:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 505;
map<string, int> mp_B;
map<string, int> mp_G;
string str_boy[maxN], str_girl[maxN], str;
int N, boy[maxN], girl[maxN], Index, b_love_g[maxN][maxN], g_deep_b[maxN][maxN];    //b_love_g表示第几男生第几喜欢的女生、g_deep_b表示第几女生对第几男生的喜欢程度
int kth[maxN]; //对应的男生选到了第几个女孩纸了
inline void marry_with_you()
{
    for(int i=1; i<=N; i++) kth[i] = 1; //每个男孩子都想先选到自己最喜欢的女孩纸
    bool flag = false;
    while(true) //不断的选自己稳定的婚姻
    {
        flag = false;
        for(int i=1; i<=N; i++) //男孩纸去选自己还能选到的女孩
        {
            if(!boy[i]) //这个男孩子还处在待嫁的年纪
            {
                int g = b_love_g[i][kth[i]++]; //男孩想去选的女孩
                if(!girl[g])    //这个女孩还没选其他的男孩纸
                {
                    boy[i] = g;
                    girl[g] = i;
                    continue;
                }
                else if(g_deep_b[g][i] > g_deep_b[g][girl[g]])  //女孩觉得这个新的男孩更好,她抛弃了原先的男盆友,(雾
                {
                    boy[girl[g]] = 0;
                    boy[i] = g;
                    girl[g] = i;
                }
                flag = true;
            }
        }
        if(!flag) break;    //这时候已经没有能结婚的人了,他们都不管是否美满已经结起来了
    }
    for(int i=1; i<=N; i++)
    {
        cout << str_boy[i] << " " << str_girl[boy[i]] << endl;  //男孩和男孩配对的女孩纸
    }
}
inline void init()
{
    Index = 0;
    mp_B.clear();
    mp_G.clear();
    for(int i=1; i<=N; i++) boy[i] = girl[i] = 0;   //他们都仍然是独立的他们
}
int main()
{
    while(scanf("%d", &N) != EOF)
    {
        init();
        for(int i=1; i<=N; i++) //男孩喜欢的女生“们”(渣
        {
            cin>>str_boy[i];
            mp_B[str_boy[i]] = i;
            for(int j=1; j<=N; j++)
            {
                cin>>str;
                if(!mp_G[str])
                {
                    mp_G[str] = ++Index;
                    str_girl[Index] = str;
                }
                b_love_g[i][j] = mp_G[str];
            }
        }
        for(int i=1; i<=N; i++) //处理女孩喜欢的男生“们”(也渣
        {
            cin>>str;
            int g = mp_G[str];
            for(int j=0; j<N; j++)
            {
                cin>>str;
                g_deep_b[g][mp_B[str]] = N - j; //喜欢的程度,越高表示的是越喜欢
            }
        }
        marry_with_you();
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值