引用刘汝佳新书--训练指南
稳定婚姻问题
题意:在一个盛大的校园舞会上有n位男生和n位女生,每人都对每个异性有一个排序,代表对他们的喜欢程度。你的任务是将男生和女生一一配对,使得男生u和女生v不存在以下情况:(1)男生u和女生v不是舞伴;(2)他们喜欢对方的程度都大于喜欢各自当前的舞伴的程度。如果出现了(2)中的情况,他们可能会擅自抛下自己的舞伴,另外组成一对。你的任务是对于每个女生,在所哟可能和她跳舞的男生中,找出她最喜欢的那个。
分析:本题就是著名的稳定婚姻问题,只是把结婚和配偶换成了跳舞和舞伴。下面用原题中的术语来介绍这个问题的Gale-Shapley算法。这个算法也称求婚-拒绝算法,因为算法的过程就是男生不停的求婚和女生不停的拒绝。
算法的详细过程是,在每一轮中,每个尚未订婚的男生在他还没有求过婚的女生中选择自己最喜欢的求婚(不管她有没有结婚)。然后每个女生在向她求婚的人之中选择她最喜欢的一个订婚,并且拒绝他人。注意,这些向她求婚的人当中包含她的未婚夫,因此她可以选择另一个自己更喜欢的人订婚,而抛弃自己现任未婚夫。当所有人都订婚时,算法结束。
// File Name: 1175.cpp // Author: zlbing // Created Time: 2013/3/1 13:32:05 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define MAXN 1050 int n; int A[MAXN][MAXN]; int B[MAXN][MAXN]; int order[MAXN]; queue<int>Q; int future_wife[MAXN]; int future_husband[MAXN]; void marry(int u,int v) { if(future_husband[v]) { future_wife[future_husband[v]]=0; Q.push(future_husband[v]); } future_husband[v]=u; future_wife[u]=v; } int main(){ int N; scanf("%d",&N); while(N--) { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&A[i][j]); } for(int i=1;i<=n;i++)order[i]=1; int a; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&a); B[i][a]=j; } CL(future_wife,0); CL(future_husband,0); while(!Q.empty())Q.pop(); for(int i=1;i<=n;i++)Q.push(i); while(!Q.empty()) { int u=Q.front();Q.pop(); if(future_wife[u])continue; int v=A[u][order[u]++]; if(!future_husband[v]) marry(u,v); else{ int vv=future_husband[v]; if(B[v][u]<B[v][vv]) marry(u,v); else Q.push(u); } } for(int i=1;i<=n;i++) printf("%d\n",future_wife[i]); if(N)printf("\n"); } return 0; }