稳定婚姻描述的是一个非常有意思的问题,关于一个群体中婚姻的稳定性~ 具体可以搜索一下,这里不再介绍。
本题就脱胎于稳定婚姻问题,给出n名男孩和n名女孩,每个男孩对n名女孩有一个“喜爱列表”,越喜欢的处于列表的越前面。要求找出一个稳定的婚姻关系,使得所有人的婚姻关系都稳定。所谓“稳定”,就是指:对于两对夫妻关系A-a, B-b,不应该存在A更喜欢b且b更喜欢A的情形,否则他们就会出轨离婚!
解决稳定混应问题较普遍的是Gale-Shapley 算法:每次从所有男孩中选出一个还没有伴侣的,从最喜爱的女性开始检查他的喜爱女性列表,如果某个女性没有伴侣,或者这名女性比起自己当前的丈夫更喜欢他,那么女性离婚而和他结婚,如此直到最后所有的男孩都有伴侣为止。可以证明,这样得到的完备婚姻是稳定的~ 具体请参考网上的资料。
话说回来,本题输入处理有点麻烦,不过总的关系并不复杂,我就瞎搞了...不过也因此在调试上费了不少时间。。。
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
using namespace std;
const int MAX = 512;
vector<int> gg[MAX], mm[MAX];
map<string, int> mmmap;
map<string, int> ggmap;
bool rej[MAX][MAX];
int match[MAX];
bool vis[MAX];
string mmlist[MAX], gglist[MAX];
int n;
int loc(int a, int b) {
for (int i = 0; i < n; ++i) {
if (mm[a][i] == b) return i;
}
}
void solve() {
memset(rej, false, sizeof(rej));
memset(match, -1, sizeof(match));
memset(vis, false, sizeof(vis));
bool ok = true;
while (ok) {
ok = false;
for (int i = 1; i <= n; ++i) {
if (!vis[i]) {
for (int j = 0; j < n; ++j) {
int &e = gg[i][j];
if (match[e] == -1) {
vis[i] = true;
match[e] = i;
break;
} else if (!rej[e][i] && loc(e, i) < loc(e, match[e])) {
vis[match[e]] = false;
vis[i] = true;
match[e] = i;
break;
} else {
rej[e][i] = true;
}
}
ok = true;
}
}
}
set<pair<string, string> > ans;
for (int i = 1; i <= n; ++i) {
ans.insert(make_pair(gglist[match[i]], mmlist[i]));
}
for (set<pair<string, string> >::iterator it = ans.begin();
it != ans.end(); ++it) {
cout << it->first << " " << it->second << endl;
}
}
int main() {
cin >> n;
string name;
int right = 0;
for (int i = 1; i <= n; ++i) {
cin >> name;
ggmap[name] = i;
gglist[i] = name;
for (int j = 1; j <= n; ++j) {
cin >> name;
if (mmmap.count(name) == 0) {
mmmap[name] = ++right;
mmlist[right] = name;
}
gg[i].push_back(mmmap[name]);
}
}
for (int i = 1; i <= n; ++i) {
cin >> name;
string him;
for (int j = 1; j <= n; ++j) {
cin >> him;
mm[mmmap[name]].push_back(ggmap[him]);
}
}
solve();
return 0;
}