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 and m 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.
稳定婚姻问题。
每次没有女友的男生在所有没有拒绝过他的女生中找一个最喜欢的表白,然后每个女生在自己的现男友和所有表白自己的男生中选一个最喜欢的接受。如果接受的是新男生的话,自己的前男友就被甩了。
可以证明【虽然我不会】,这种方法一定可以得到解,得到的解一定是可行解,而且这一解在所有解中对男生最优,对女生最劣。
#include<cstdio>
#include<cstring>
#define M(a) memset(a,0,sizeof(a))
int mrk[30][30],frk[30][30],cs[30][30],wf[30],hs[30],n,mnm[30],fnm[30],mnb[30],fnb[30];
bool ref[30][30];
void init()
{
char s[50];
int i,j,k,x,y,z;
M(mrk);
M(frk);
M(cs);
M(wf);
M(hs);
M(ref);
M(mnm);
M(fnm);
M(mnb);
M(fnb);
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%s",s+1);
mnm[i]=s[1]-'a'+1;
mnb[s[1]-'a'+1]=i;
}
for (i=1;i<=n;i++)
{
scanf("%s",s+1);
fnm[i]=s[1]-'A'+1;
fnb[s[1]-'A'+1]=i;
}
for (i=1;i<=n;i++)
{
scanf("%s",s+1);
x=mnb[s[1]-'a'+1];
for (k=1;k<=n;k++)
mrk[x][k]=fnb[s[k+2]-'A'+1];
}
for (i=1;i<=n;i++)
{
scanf("%s",s+1);
x=fnb[s[1]-'A'+1];
for (k=1;k<=n;k++)
frk[x][k]=mnb[s[k+2]-'a'+1];
}
}
void solve()
{
int i,j,k,x,y,z;
bool b;
while (1)
{
b=0;
M(cs);
for (i=1;i<=n;i++)
if (!wf[i])
{
b=1;
for (j=1;j<=n;j++)
if (!ref[i][mrk[i][j]])
{
cs[i][mrk[i][j]]=1;
break;
}
}
if (!b) return;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
if (cs[frk[i][j]][i])
{
wf[frk[i][j]]=i;
if (hs[i])
{
wf[hs[i]]=0;
ref[hs[i]][i]=1;
}
hs[i]=frk[i][j];
break;
}
if (frk[i][j]==hs[i]) break;
}
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (cs[i][j]&&hs[j]!=i)
ref[i][j]=1;
}
}
void prt()
{
int i,j,k;
for (i=1;i<=26;i++)
if (mnb[i])
printf("%c %c\n",i+'a'-1,fnm[wf[mnb[i]]]+'A'-1);
}
int main()
{
int T,i;
scanf("%d",&T);
while (T--)
{
init();
solve();
prt();
if (T) printf("\n");
}
}