UVALive - 3989 Ladies' Choice 稳定婚姻问题

Teenagers from the local high school have asked you to help them with the organization of next year’s
Prom. The idea is to find a suitable date for everyone in the class in a fair and civilized way. So,
they have organized a web site where all students, boys and girls, state their preferences among the
class members, by ordering all the possible candidates. Your mission is to keep everyone as happy as
possible. Assume that there are equal numbers of boys and girls.
Given a set of preferences, set up the blind dates such that there are no other two people of opposite
sex who would both rather have each other than their current partners. Since it was decided that the
Prom was Ladies’ Choice, we want to produce the best possible choice for the girls.
Input
Input consists of multiple test cases the first line of the input contains the number of test cases.
There is a blank line before each dataset.
The input for each dataset consists of a positive integer N, not greater than 1,000, indicating the
number of couples in theclass. Next, there are N lines, each onecontaining the all the integers from 1
to N,ordered according to the girl’s preferences. Next, there are N lines, each one containing all the
integers from 1 to N, ordered according to the boy’s preferences.
Output
The output for each dataset consists of a sequence of N lines, where the i-th line containsthe number
of the boy assigned to the i-th girl (from 1 to N).
Print a blank line between datasets.
Sample Input
1
5
1 2 3 5 4
5 2 4 3 1
3 5 1 2 4
3 4 2 1 5
4 5 1 2 3
2 5 4 1 3
3 2 4 1 5
1 2 4 3 5
4 1 2 5 3
5 3 2 4 1
Sample Output
1
2
5
3
4 

本题就是著名的稳定婚姻问题,只是把结婚换成跳舞选舞伴。

稳定婚姻问题。稳定婚姻问题是一个很有意思的匹配问题。有n位男士和n位女士,每人都对每个异性有一个排序,代表对他们的喜欢程度。现在希望给每位男士找一位不同的女士做配偶,使得每人恰好有一个异性配偶。如果男士u和女士v不是配偶但喜欢对方的程度都大于喜欢各自当前配偶,则称他们为一个不稳定对(unstablepair)。如果一个配对方案存在不稳定对则此对可能会破坏原来的配对方案。稳定婚姻问题是希望找出一个不含不稳定对的方案。

稳定婚姻问题的经典算法为求婚-拒绝算法(propose-and-reject algorithm),即男士按自己喜欢程度从高到低依次给每位女士主动求婚,直到有一个接受他。女士每次遇到比当前配偶更差的男士时拒绝他,遇到更喜欢的男士时就接受他,并抛弃以前的配偶。被抛弃的男士继续按照列表向剩下的女士依次求婚,直到所有人都有配偶。看起来女士更有选择权,但实际上最后得到的结果是男士最优(man-optimal)的。

在这个算法中,所有男士可以娶到自己有可能娶到的最好妻子,而女士则未必。

本题中,需要我们求出女生可能嫁到的最好的男生,所以我们将算法做小小改动,让女生求婚,男生拒绝,这样女生就能找到自己最喜欢的并且有可能嫁给的最好的男生。

由此题可见,主动才能赢得人生啊。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <set>
#include <map>
#include <cctype>
#include <list>
#include <cmath>
#include <bitset>
#include <queue>
#include <deque>
#include <stack>
#include <sstream>
#include <functional>
#include <cassert>
using namespace std;

#define tmax(a, b) if (b > a) a = b
#define tmin(a, b) if (b < a) a = b
#define lson(a) a << 1
#define rson(a) (a << 1) | 1
char inc() { char _[10]; scanf("%s", _); return _[0]; }
int ini() { int _; scanf("%d", &_); return _; }
long long inll() { long long _; scanf("%I64d", &_); return _; }
double ind() { double _; scanf("%lf", &_); return _; }
string ins() { string _; cin >> _; return _; }
int inl(char _[]) { if (!fgets(_, (int)1e8, stdin)) return -1; int i = strlen(_); if (_[i - 1] == '\n') _[--i] = 0; return i; }

typedef pair<int, int> pii;
typedef pair<char, char> pcc;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const LL lnf = 0x3f3f3f3f3f3f3f3f;
const double pi = 3.14159265358979323846;
const double eps = 1e-8;
const int mod = 100007;
const int maxn = 1e3 + 10;

int n, husband[maxn], wife[maxn];
int hbRank[maxn][maxn], wfRank[maxn][maxn];
int fail[maxn];
queue<int> que;

void Engage(int man, int woman) {
	int cur = wife[man];
	if (cur) {
		que.push(cur);
	}
	wife[man] = woman;
	husband[woman] = man;
}

int main() {
	int CAS = 0;
	//std::ios::sync_with_stdio(0);
	//std::cin.tie(0);
#ifdef NIGHT_13
	//freopen("myout.txt", "w", stdout);
	freopen("in.txt", "r", stdin);
	int time_night_13 = clock();
#endif // NIGHT_13


	int t = ini();
	while (t--) {
		scanf("%d", &n);
		for (int i = 1; i <= n; ++i) {
			que.push(i);
			for (int j = 1; j <= n; ++j) {
				hbRank[i][j] = ini();
			}
		}
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				wfRank[i][ini()] = j;
			}
		}
		memset(fail, 0, sizeof fail);
		memset(wife, 0, sizeof wife);
		while (!que.empty()) {
			int woman = que.front(); que.pop();
			int man = hbRank[woman][++fail[woman]];
			if (!wife[man] || wfRank[man][wife[man]] > wfRank[man][woman]) {
				Engage(man, woman);
			} else {
				que.push(woman);
			}
		}
		for (int i = 1; i <= n; ++i) { printf("%d\n", husband[i]); }
		if (t) puts("");
	}

#ifdef NIGHT_13
	fprintf(stderr, "- - - - Time: %dms - - - -\n", (int)clock() - time_night_13);
#endif // NIGHT_13
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值