HDU 1522 -- Marriage is Stable (模板题&总结稳定婚姻算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1522

Marriage is Stable

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1299    Accepted Submission(s): 690
Special Judge


Problem Description
Albert, Brad, Chuck are happy bachelors who are in love with Laura, Marcy, Nancy. They all have three choices. But in fact, they do have some preference in mind. Say Albert, he likes Laura best, but that doesn't necesarily mean Laura likes him. Laura likes Chuck more than Albert. So if Albert can't marry Laura, he thinks Nancy a sensible choice. For Albert, he orders the girls Laura > Nancy > Marcy.

For the boys:

Albert: Laura > Nancy > Marcy
Brad: Marcy > Nancy > Laura
Chuck: Laura > Marcy > Nancy

For the girls:

Laura: Chuck > Albert > Brad
Marcy: Albert > Chuck > Brad
Nancy: Brad > Albert > Chuck

But if they were matched randomly, such as

Albert <-> Laura 
Brad <-> Marcy
Chuck <-> Nancy

they would soon discover it's not a nice solution. For Laura, she likes Chuck instead of Albert. And what's more, Chuck likes Laura better than Nancy. So Laura and Chuck are likely to come together, leaving poor Albert and Nancy.

Now it's your turn to find a stable marriage. A stable marriage means for any boy G and girl M, with their choice m[G] and m[M], it will not happen that rank(G, M) < rank(G, m[G])and rank(M, G) < rank(M, m[M]).
 
 
Input
Each case starts with an integer n (1 <= n <= 500), the number of matches to make.

The following n lines contain n + 1 names each, the first being name of the boy, and rest being the rank of the girls.

The following n lines are the same information for the girls.

Process to the end of file.
 
 
Output
If there is a stable marriage, print n lines with two names on each line. You can choose any one if there are multiple solution. Print "Impossible" otherwise.

Print a blank line after each test.
 
 
Sample Input
3
Albert Laura Nancy Marcy
Brad Marcy Nancy Laura
Chuck Laura Marcy Nancy
Laura Chuck Albert Brad
Marcy Albert Chuck Brad
Nancy Brad Albert Chuck
 
 
Sample Output
Albert Nancy
Brad Marcy
Chuck Laura
 
 
稳定婚姻算法(G-S算法)介绍:

一、问题引入

有n个男生n个女生,每个男生依照喜欢程度对n个女生进行了排序,同理每个女生也依照喜欢程度对n个男生进行了排序,现要将他们一一配对,要求所有的配对是稳定的,即不会出现一个女生相对自己配对的男生更喜欢另一个男生,而这个男生也更喜欢她的情况。

二、算法步骤描述:

  第一轮,每个男人都选择自己名单上排在首位的女人,并向她表白。这种时候会出现两种情况:

(1)该女士还没有被男生追求过,则该女士接受该男生的请求。

(2)若该女生已经接受过其他男生的追求,那么该女生会将该男士与她的现任男友进行比较,若更喜欢她的男友,那么拒绝这个人的追求,否则,抛弃其男友……

  第一轮结束后,有些男人已经有女朋友了,有些男人仍然是单身。

       在第二轮追女行动中,每个单身男都从所有还没拒绝过他的女孩中选出自己最中意的那一个,并向她表白,不管她现在是否是单身。这种时候还是会遇到上面所说的两种情况,还是同样的解决方案。直到所有人都不再是单身。

 三、算法总结:

(1)无论男子的迭代排序如何,G-S算法每次返回的匹配S都是唯一的;

(2)匹配S中所有求爱方的伴侣是他们各自的最佳有效伴侣(the best valid partner);

(3)匹配S中所有被求爱方的伴侣是他们各自的最差有效伴侣(the wrost valid partner);

(4)也就是说,对于任意可以进行稳定匹配的二分图,对于任意点集,其最佳(差)有效伴侣是互不相同的。

 

题意:有n个男生和n个女生,每行给出每个人的名字,后面跟着对n个异性的好感度排名,要求输出男女两两结合的稳定婚姻匹配。

解析:此题关键在于将字符串之间的关系转换成编号关系,然后套用稳定婚姻算法即可,下面为AC代码(可作为稳定匹配算法模板)。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <map>
 4 #include <string>
 5 #define MAXN 510
 6 using namespace std;
 7 int mm[MAXN][MAXN], gg[MAXN][MAXN], p[MAXN];  // p[i]表示第i个boy已表白人数
 8 // mm[i][j]表示第i个girl对编号为j的boy的好感排位,gg[i][j]表示第i个boy第j喜欢的girl编号,注意意义不同
 9 int gg_match[MAXN], mm_match[MAXN];  // gg_match[i]表示第i个boy已匹配的girl编号
10 string ss[MAXN*2], str;   // ss[i]表示编号为i的name
11 map<string, int> mp_mm, mp_gg;  // name映射编号
12 
13 int main() {
14     int n;
15     while (cin >> n) {
16         mp_gg.clear(); mp_mm.clear();
17         int cnt = 0;  // 按照girl出现次序给予编号
18         for (int i = 1; i <= n; i++) {
19             cin >> ss[i];
20             mp_gg[ss[i]] = i;
21             for (int j = 1; j <= n; j++) {
22                 cin >> str;
23                 if (mp_mm[str] == 0) {
24                     mp_mm[str] = ++cnt;
25                     ss[n+cnt] = str;
26                 }
27                 gg[i][j] = mp_mm[str];
28             }
29         }
30         for (int i = 1; i <= n; i++) {
31             cin >> str;
32             int a = mp_mm[str];
33             for (int j = 1; j <= n; j++) {
34                 cin >> str;
35                 int b = mp_gg[str];
36                 mm[a][b] = j;
37             }
38         }
39         bool flag = true;  // 此处开始为算法核心代码,前面只是将字符串关系处理为编号关系
40         for (int i = 1; i <= n; i++) p[i] = 1;
41         memset(mm_match, -1, sizeof(mm_match));
42         memset(gg_match, -1, sizeof(gg_match));
43         while (flag) {
44             flag = false;
45             for (int i = 1; i <= n; i++) {
46                 if (gg_match[i] == -1 && p[i] <= n) {
47                     int a = gg[i][p[i]++];
48                     if (mm_match[a] == -1) mm_match[a] = i, gg_match[i] = a;
49                     else if (mm[a][i] < mm[a][mm_match[a]]) {
50                         gg_match[i] = a;
51                         gg_match[mm_match[a]] = -1;
52                         mm_match[a] = i;
53                     }
54                     flag = true;
55                 }
56             }  // end for
57         } // end while
58         for (int i = 1; i <= n; i++) cout << ss[i] << ' ' << ss[gg_match[i]+n] << endl;
59     }
60     return 0;
61 }
View Code

 

顺便贴上另外两道稳定匹配题目的AC代码:

poj 3487 -- The Stable Marriage Problem

 1 #include <iostream>
 2 #include <cstring>
 3 #include <map>
 4 #define MAXN 30
 5 using namespace std;
 6 int mm[MAXN][MAXN], gg[MAXN][MAXN], p[MAXN];
 7 int gg_match[MAXN], mm_match[MAXN];
 8 char idx[2*MAXN];
 9 map<char, int> mp;
10 int main() {
11     int t, n;
12     cin >> t;
13     while (t--) {
14         cin >> n;
15         char ch;
16         int cnt = 0;
17         mp.clear();
18         for (int i = 0; i < 2 * n; i++) cin >> ch;
19         for (int i = 1; i <= n; i++) {
20             cin >> idx[i] >> ch;
21             mp[idx[i]] = i;
22             for (int j = 1; j <= n; j++) {
23                 cin >> ch;
24                 if (mp[ch] == 0) {
25                     mp[ch] = ++cnt;
26                     idx[cnt+n] = ch;
27                 }
28                 gg[i][j] = mp[ch];
29             }
30         }
31         for (int i = 1; i <= n; i++) {
32             char gir;
33             cin >> gir >> ch;
34             int a = mp[gir];
35             for (int j = 1; j <= n; j++) {
36                 cin >> ch;
37                 int b = mp[ch];
38                 mm[a][b] = j;
39             }
40         }
41         bool flag = true;
42         for (int i = 1; i <= n; i++) p[i] = 1;
43         memset(mm_match, -1, sizeof(mm_match));
44         memset(gg_match, -1, sizeof(gg_match));
45         while (flag) {
46             flag = false;
47             for (int i = 1; i <= n; i++) {
48                 if (gg_match[i] == -1 && p[i] <= n) {
49                     int a = gg[i][p[i]++];
50                     if (mm_match[a] == -1) mm_match[a] = i, gg_match[i] = a;
51                     else if (mm[a][i] < mm[a][mm_match[a]]) {
52                         gg_match[i] = a;
53                         gg_match[mm_match[a]] = -1;
54                         mm_match[a] = i;
55                     }
56                     flag = true;
57                 }
58             }
59         }
60         for (int i = 0; i < 26; i++) {
61             for (int j = 1; j <= n; j++) if (idx[j] == 'a' + i) {
62                 cout << idx[j] << ' ' << idx[gg_match[j]+n] << endl;
63                 break;
64             }
65         }
66         if (t) cout << endl;
67     }
68     return 0;
69 }
View Code

hdu 1435 -- Stable Match

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #define MAXN 210
 6 using namespace std;
 7 int gg[MAXN][MAXN], mm[MAXN][MAXN];
 8 int gg_match[MAXN], mm_match[MAXN], p[MAXN];
 9 struct node{
10     double len;
11     int cap, idx;
12 } aim[MAXN];
13 struct input{
14     int idx, cap;
15     double x, y, z;
16 } lau[MAXN], acc[MAXN];
17 bool cmp(const node &a, const node &b) {
18     if (fabs(a.len - b.len) < 0.000001) return a.cap > b.cap;
19     else return a.len < b.len;
20 }
21 
22 int main() {
23     int t;
24     cin >> t;
25     while (t--) {
26         int n; cin >> n;
27         for (int i = 1; i <= n; i++) cin >> lau[i].idx >> lau[i].cap >> lau[i].x >> lau[i].y >> lau[i].z;
28         for (int i = 1; i <= n; i++) cin >> acc[i].idx >> acc[i].cap >> acc[i].x >> acc[i].y >> acc[i].z;
29         for (int i = 1; i <= n; i++) {
30             for (int j = 1; j <= n; j++) {
31                 aim[j].len = sqrt((lau[i].x-acc[j].x)*(lau[i].x-acc[j].x) + (lau[i].y-acc[j].y)*(lau[i].y-acc[j].y) + (lau[i].z-acc[j].z)*(lau[i].z-acc[j].z));
32                 aim[j].cap = acc[j].cap; aim[j].idx = acc[j].idx;
33             }
34             sort(aim+1, aim+n+1, cmp);
35             for (int j = 1; j <= n; j++) gg[lau[i].idx][j] = aim[j].idx;
36         }
37         for (int i = 1; i <= n; i++) {
38             for (int j = 1; j <= n; j++) {
39                 aim[j].len = sqrt((acc[i].x-lau[j].x)*(acc[i].x-lau[j].x) + (acc[i].y-lau[j].y)*(acc[i].y-lau[j].y) + (acc[i].z-lau[j].z)*(acc[i].z-lau[j].z));
40                 aim[j].cap = lau[j].cap; aim[j].idx = lau[j].idx;
41             }
42             sort(aim+1, aim+n+1, cmp);
43             for (int j = 1; j <= n; j++) mm[acc[i].idx][aim[j].idx] = j;
44         }
45         bool flag = true;
46         for (int i = 1; i <= n; i++) p[i] = 1;
47         memset(mm_match, -1, sizeof(mm_match));
48         memset(gg_match, -1, sizeof(gg_match));
49         while (flag) {
50             flag = false;
51             for (int i = 1; i <= n; i++) {
52                 if (gg_match[i] == -1 && p[i] <= n) {
53                     int a = gg[i][p[i]++];
54                     if (mm_match[a] == -1) mm_match[a] = i, gg_match[i] = a;
55                     else if (mm[a][i] < mm[a][mm_match[a]]) {
56                         gg_match[i] = a;
57                         gg_match[mm_match[a]] = -1;
58                         mm_match[a] = i;
59                     }
60                     flag = true;
61                 }
62             }
63         }
64         for (int i = 1; i <= n; i++) cout << i << ' ' << gg_match[i] << endl;
65         cout << endl;
66     }
67     return 0;
68 }
View Code

 

posted @ 2018-02-04 10:16  _kangkang  阅读(505)  评论(0编辑  收藏  举报