Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1959 | Accepted: 835 |
Description
The stable marriage problem consists of matching members of two different sets according to the member’s preferences for the other set’s members. The input for our problem consists of:
- a set M of n males;
- a set F of n females;
- for each male and female we have a list of all the members of the opposite gender in order of preference (from the most preferable to the least).
A marriage is a one-to-one mapping between males and females. A marriage is called stable, if there is no pair (m,f) such that f ∈ F prefers m ∈ M to her current partner andm prefers f over his current partner. The stable marriage A is called male-optimal if there is no other stable marriage B, where any male matches a female he prefers more than the one assigned in A.
Given preferable lists of males and females, you must find the male-optimal stable marriage.
Input
The first line gives you the number of tests. The first line of each test case contains integer n (0 < n < 27). Next line describes n male and n female names. Male name is a lowercase letter, female name is an upper-case letter. Then go n lines, that describe preferable lists for males. Next n lines describe preferable lists for females.
Output
For each test case find and print the pairs of the stable marriage, which is male-optimal. The pairs in each test case must be printed in lexicographical order of their male names as shown in sample output. Output an empty line between test cases.
Sample Input
2 3 a b c A B C a:BAC b:BAC c:ACB A:acb B:bac C:cab 3 a b c A B C a:ABC b:ABC c:BCA A:bac B:acb C:abc
Sample Output
a A b B c C a B b A c C
來自網上某大牛:
穩定婚姻問題(The Stable Marriage Problem)” 大致說的就是100個SSGG和100個PPMM按照自己的喜歡程度給所有異性打分排序。每個帥哥都憑自己好惡給每個MM打分:我最愛a,其次愛b,再次愛c...每個帥哥打的分不同,你最愛的可能是我最討厭的我最愛的可能是他不甚喜歡的。同樣,每個美女也同樣給每個帥哥打分。現在需要給他們搭配出100 對新郎新娘,並且要保證所得到是穩定婚姻的搭配。那麼,什麼是不穩定的婚姻呢?所謂不穩婚姻是說, 比如說有兩對夫婦(M1、F1)和(M2、F2),M1的老婆是F1,但他更愛F2;而F2的老公雖說是M2,但她更愛M1——這樣的婚姻就是不穩婚姻,M1和F2理應結合,他們現在各自的婚姻都是錯誤。 那麼,我們如何找到一個算法來構造這100個穩定婚姻呢?這個是數學界切切實實研究過的問題。對於以前沒有接觸過這個問題的人,這個理論最出人意外的結論是: 傳統的求愛、結婚過程是male-optimal(男生主動)的,也就是說,男性能夠得到儘可能好的心上人,女性卻不然。這個問題和圖論有關, 最早是由兩個美國數學家1962年在American Mathematical Monthly上提出的,相關的參考文獻其實很多,下面這個網頁大概是講得最通俗易懂的: "The Stable Marriage Problem" by Harry Mairson,http://www.cs.columbia.edu/~evs/intro/stable/writeup.html 那麼,開始激動人心求婚過程啦 第一天上午, 所有的男生都向自己最愛的美眉求婚。下午,每個MM看看自己有沒有收到, 收到了多少人的求婚。如果只收到一個男生的求婚,那麼就和他訂婚。如果收到多於一個GG的求婚,那麼就和其中她最愛的那個男人訂婚,同時把其他男人都拒掉。如果一個求婚都沒有,不要着急,最後總會有的。晚上,檢查一遍,如果所有MM都訂婚了,OK,萬事大吉,明天舉行集體婚禮! 但如果還有人沒有訂婚,那麼事情還沒有完,第二天還得重複。 第二天上午,所有還沒訂婚的男生向自己次愛的美眉求婚(因爲昨天已經被他們的最愛拒絕了)下午,每個MM再看一遍自己收到訂婚的情況。如果她已經訂婚了,但是又有一個她更愛的男人來向她求婚,那就把原來那個拒絕掉,再和這個更愛的男人訂婚;如果還沒訂婚,那就和第一天的下午的處理一樣。晚上再檢查一遍,如果還是有人沒有訂婚,那第三天再重複。 第三天上午,所有沒有訂婚的GG,包括第一天訂了第二天又被踹出來的(看來要有點憂患意識),再向還沒有拒絕過他的MM中他最愛的那個求婚 ...... 如此周而復始,直到最後大家都訂了婚,便一起結婚!哈哈,恭喜恭喜 這麼個過程,數學上可以證明如下性質: 1) 這個過程會中止,也就是說,總有大家都訂了婚的一天,不可能無限循環。 2) 中止後所有的婚姻是穩定婚姻。我們能證明的是,通過上面那個求婚過程,所有的婚姻都是穩定的,沒有人犯錯誤。 3) 比較引人注目的是,這個過程是male-optimal(男生主動)的,男性能夠獲得儘可能好的伴侶,比如說最後有二十個女人拒絕了他,他仍然能夠得到剩下的八十個女人中他最愛的那一個。 4) 更有甚者,這個過程是female-pessimal的,女人總是在可能的情況下被最不喜歡的人追上:eek:。這一點沒有那麼直觀的理解,勉強要解釋的話,可以這麼看:雖說女人每換一次訂婚對象,都往上升一層,但起點可能很低,雖說在一步步接近她最愛的目標,但最後往往達不到。比如說還差三十名就達到她最愛的人了,但這時Game Over,所有的人都已訂了婚,這樣她也只能死了心了!還有三十個她更愛的人還沒向她求過婚,可是她也無可奈何了...
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define maxn 30
int a[200];//a[a+i]表示男士a+i的編號爲i,a[A+j]表示女士A+j的編號爲j
int prefer_male[maxn][maxn],prefer_female[maxn][maxn];//男女士偏好表
int match_female[maxn],match_male[maxn];//記錄男女士現任女男友的編號
int lettle[maxn][maxn];//表示女士i今天收到的第j封信的作者編號(即對第i女士表白的第j個男士的標號)
int num_lettle[maxn];//記錄第i天的信的數量
int curpoint[maxn];//記錄男士下一次表白的女士
int n;
bool finish()//所有男士都有女友結束
{
for(int i=0; i<n; i++)
if(match_male[i]==-1)
return false;
return true;
}
int find_pos(int male,int female)//返回女士對男士的評價值
{
for(int i=0; i<n; i++)
if(male==prefer_female[female][i])
return i;
}
void solve()
{
int i,j;
memset(match_male,-1,sizeof(match_male));
memset(match_female,-1,sizeof(match_female));
memset(curpoint,0,sizeof(curpoint));
while(!finish())
{
memset(num_lettle,0,sizeof(num_lettle));
memset(lettle,-1,sizeof(lettle));
for(i=0; i<n; i++)//男士表白寫信
{
if(match_male[i]==-1)
{
lettle[prefer_male[i][curpoint[i]]][num_lettle[prefer_male[i][curpoint[i]]]++]=i;
//prefer_male[i][curpoint[i]表示第i個男士第curpoint[i]個喜歡的女士編號
//num_lettle[prefer_male[i][curpoint[i]]]表示該女士收到信的個數
//整天表示該女士一天收到信的作者編號
curpoint[i]++;
}
}
for(i=0; i<n; i++)//女士看信
{
if(match_female[i]==-1&&num_lettle[i]==1)//只有一個人表白,女士別無選擇了
{
match_female[i]=lettle[i][0];
match_male[lettle[i][0]]=i;
}
else if(match_female[i]==-1&&num_lettle[i]>1)//多個人表白,女士要選自己最喜歡的了
{
int favor=lettle[i][0];
for(j=1; j<num_lettle[i]; j++)
{
if(find_pos(lettle[i][j],i)<find_pos(favor,i))
favor=lettle[i][j];
}
match_female[i]=favor;
match_male[favor]=i;
}
else if(match_female[i]!=-1&&num_lettle[i]!=0)//女士已經有男友,但是還是收到表白信,
{ //她會再重新選擇自己最喜歡的,現任男友就被甩了,囧啊!
int favor=-1;
for(j=0; j<num_lettle[i]; j++)
{
if(find_pos(lettle[i][j],i)<find_pos(match_female[i],i))
favor=lettle[i][j];
}
if(favor!=-1)
{
match_male[match_female[i]]=-1;//被甩了~~~~
match_female[i]=favor;//新人成對,O(∩_∩)O~
match_male[favor]=i;
}
}
}
}
}
int main()
{
int t;
char temp;
cin>>t;
while(t--)
{
cin>>n;
for(int i=0; i<n; i++)//輸入編號
{
cin>>temp;
a[temp]=i;
}
for(int j=0; j<n; j++)
{
cin>>temp;
a[temp]=j;
}
for(int i=0; i<n; i++)//男女士對異性評價值
{
cin>>temp;
int male=temp;
cin>>temp;
for(int j=0; j<n; j++)
{
cin>>temp;
prefer_male[a[male]][j]=a[temp];
}
}
for(int i=0; i<n; i++)
{
cin>>temp;
int female=temp;
cin>>temp;
for(int j=0; j<n; j++)
{
cin>>temp;
prefer_female[a[female]][j]=a[temp];
}
}
solve();
for(int i=0; i<n; i++)//輸出,挺有才
for(int j='a'; j<='z'; j++)
{
if(a[j]==i)
{
putchar(j);
putchar(' ');
int index=match_male[i];
for(int k='A'; k<='Z'; k++)
if(a[k]==index)
{
putchar(k);
break;
}
cout<<endl;
break;
}
}
if(t!=0)
cout<<endl;
}
return 0;
}
另附一連接:用(穩定婚姻 Gale-Shapley算法 )