这道题和最标准的稳定匹配不同的,就是男和女不是一个配一个,学生可能一个学校都不能去,但一个学校却有可能录取多个学生,其他都一样。所以原来的模板,只需要改动woman数组,就是这个程序中的Woman数组。为了方便,把学生看成男,把学校看成女,那么Woman数组中对于每一个女性,都要保存目前所选的学生,不断更新。这道题除了要求稳定性,还有一个隐含的要求就是不能够再找出一组男女搭配,加入到答案中还是不会出现私奔的情况。那么假设算法结束后,现在一个男性单身,他可以再找到一个女性组成这样的搭配,这个男性已经向所有的女性告白过了,包括现在将要和他搭配的女性,那么当时这个女人拒绝他就是因为名额已经满了并且都比他好,所以这个女性一定是没法和他在一起的,假设不成立。
关于cmp函数的写法要注意,return a > b就是降序排列,return a < b就是升序排列。
一般此类题都要写成结构体形式,然后有些时候每个人要自带一个编号,避免排序以后将顺序打乱。
这道题还有一个vis数组,在这题中Man出现0是允许的,只有在所有的男性都把女性告白一遍以后才停止。
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<cmath>
#include<algorithm>
#define N 200
using namespace std;
struct node
{
int region;
int score;
int num;
int sum;
int like[N];
}man[N];
struct node2
{
int region;
int c;
}woman[N];
int T, n, m, flag, f, womanpos, y, r, maxx, numm;
int ranke[N][N], ranks[N][N], tmpman[N], cnt[N], Man[N], Woman[N][N], vis[N];
bool cmp(node a, node b)
{
if (a.region == r && b.region == r || a.region != r && b.region != r)
{
return a.score > b.score;
}
else
if (a.region == r && b.region != r)
{
return a.score > b.score*0.7;
}
else
{
return a.score*0.7 > b.score;
}
}
bool cmp2(node a, node b)
{
return a.num < b.num;
}
void sortrank()
{
memset(ranks, 0, sizeof(ranks));
memset(ranke, 0, sizeof(ranke));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= man[i].sum; j++)
ranks[i][j] = man[i].like[j];
for (int i = 1; i <= m; i++)
{
r = woman[i].region;
sort(man+1, man+n+1, cmp);
for (int j = 1; j <= n; j++)
ranke[i][man[j].num] = j;
}
}
void GS()
{
memset(Man, 0, sizeof(Man));
memset(Woman, 0, sizeof(Woman));
memset(cnt, 0, sizeof(cnt));
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++) tmpman[i] = 1;
sort(man+1, man+n+1, cmp2);
flag = 1;
while (flag)
{
flag = 0;
for (int i = 1; i <= n; i++)
if (Man[i] == 0 && vis[i] == 0)
{
flag = 1;
if (tmpman[i] > man[i].sum)
{
vis[i] = 1;
continue;
}
womanpos = ranks[i][tmpman[i]];
if (cnt[womanpos] < woman[womanpos].c)
{
cnt[womanpos]++;
Woman[womanpos][cnt[womanpos]] = i;
tmpman[i]++;
Man[i] = womanpos;
}
else
{
maxx = ranke[womanpos][i];
f = 0;
for (int j = 1; j <= cnt[womanpos]; j++)
{
if (ranke[womanpos][Woman[womanpos][j]] > maxx)
{
f = 1;
maxx = ranke[womanpos][Woman[womanpos][j]];
numm = j;
}
}
if (f == 1)
{
y = Woman[womanpos][numm];
Woman[womanpos][numm] = i;
Man[y] = 0;
Man[i] = womanpos;
tmpman[i]++;
}
else
tmpman[i]++;
}
}
}
}
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
man[i].num = i;
scanf("%d%d%d", &man[i].region, &man[i].score, &man[i].sum);
for (int j = 1; j <= man[i].sum; j++)
scanf("%d", &man[i].like[j]);
}
for (int i = 1; i <= m; i++)
scanf("%d%d", &woman[i].region, &woman[i].c);
sortrank();
GS();
for (int i = 1; i <= n; i++)
if (vis[i] == 1)
printf("not accepted\n");
else printf("%d\n", Man[i]);
if (T) printf("\n");
}
return 0;
}