UVa 11119 - Chemical Attraction

contents

  1. 1. Problem
  2. 2. Sample Input
  3. 3. Sample Output
  4. 4. Solution

Problem

給予由陰陽離子構成的化合物,混和後會根據活性表發生變化,求其中一種穩定態。

所謂的穩定態,就是不會兩個化合物之間可以進行陰陽離子的互換。

Sample Input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
3
Ba Sr Th
3
Cl Br Fl
1 2 3
1 3 2
2 1 3
2 1 3
1 3 2
1 2 3
3
BaFl SrBr ThCl
5
BaFl BaFl SrFl SrCl ThFl
0
3
Na Ag Fe
5
Su Zi Xe Ar Do
1 2 4 3 5
5 3 1 2 4
2 3 1 4 5
3 2 1
3 2 1
1 3 2
1 2 3
2 1 3
10
NaDo AgDo AgAr FeXe NaXe
AgZi AgZi NaSu AgSu FeDo
0
0

Sample Output

1
2
3
4
5
6
7
8
Scenario 1, Mixture 1:
BaCl SrBr ThFl
Scenario 1, Mixture 2:
BaFl BaCl SrFl SrFl ThFl
Scenario 2, Mixture 1:
NaDo AgSu AgSu FeDo NaXe AgZi AgZi NaXe AgAr FeDo

Solution

一個經典的穩定婚姻問題 (stable marriage problem),可以用 Gale-Shapley algorithm 解決匹配兩邊個數相同的穩定婚姻。穩定婚姻有兩組最優解,其中一組最優解於男方、另外一組為女方,其最優解即為候選的排序為字典順序最小的。

假設現在要給男方一個最優解,那麼根據貪心的思路,男方要不斷地按照排名清單去向女方求婚,如果女方心中對求婚男方的排名更好,則男方求婚成功,而前男友就會被拋棄,被拋棄的男方將會根據清單再找下去。做法類似增廣路徑。

為什麼這樣能趨近穩定呢?原因是這樣子的,由於男方不斷地求婚,女方配對男方的排名會越來越好,男方被拋棄後,求婚對象則會越來越差。

假定男方為 A, B,女方為 1, 2,優先順序為括弧內,越靠前表示順位越高。

1
2
A(1, 2) - 1(B, A)
B(1, 2) - 2(A, B)

假如 A - 1B - 2,則女 1 更喜歡男 A,女 2 更喜歡男 B,男方中也更喜歡對方的配偶 (這個例子中是相同),而造成配對交換,這即為不穩定婚姻。

解決會交換的情況。當嘗試配對一對男女時,如何保證不會發生循環交換?當男主被某女拋棄,則表示某女心中有一個更好的某男。男方按照順序求婚,就不會發生男方中會更喜歡對方的配偶而交換。

單看女方,了解到拋棄的動作是有限的,算法就能在 O(N^2) 解決。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Gale-Shapley algorithm, stable marriage problem
#include <stdio.h>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 256;
class GaleShapley { // produce the best possible choice for the mans
public:
int mOrder[MAXN][MAXN], fOrder[MAXN][MAXN];
int fPref[MAXN][MAXN];
int man[MAXN], woman[MAXN];
int N;
void init(int n) {
N = n;
}
void stable() {
int mIdx[MAXN];
for (int i = 0; i < N; i++)
man[i] = woman[i] = -1, mIdx[i] = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
fPref[i][fOrder[i][j]] = j;
}
for (int i = 0; i < N; i++) {
int m = i, w;
while (m >= 0) {
w = mOrder[m][mIdx[m]++];
while (m >= 0 && (woman[w] == -1 || fPref[w][woman[w]] > fPref[w][m])) {
man[m] = w;
swap(m, woman[w]);
}
}
}
}
} g;
char s[MAXN];
int tA[MAXN][MAXN], tB[MAXN][MAXN], rtA[MAXN][MAXN], rtB[MAXN][MAXN];
int main() {
int N, M, x, n;
int cases = 0;
while (scanf("%d", &N) == 1 && N) {
map<string, int> Rn, Rm;
for (int i = 0; i < N; i++)
scanf("%s", s), Rn[s] = i;
scanf("%d", &M);
for (int i = 0; i < M; i++)
scanf("%s", s), Rm[s] = i;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
scanf("%d", &tA[i][j]), tA[i][j]--, rtA[i][tA[i][j]] = j;
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
scanf("%d", &tB[i][j]), tB[i][j]--, rtB[i][tB[i][j]] = j;
++cases;
int tcases = 0;
while (scanf("%d", &n) == 1 && n) {
vector<string> A, B;
for (int i = 0; i < n; i++) {
scanf("%s", s);
string a(2, 'a'), b(2, 'a');
a[0] = s[0], a[1] = s[1];
b[0] = s[2], b[1] = s[3];
A.push_back(a), B.push_back(b);
}
g.init(n);
for (int i = 0; i < n; i++) {
vector< pair<int, int> > p;
int u = Rn[A[i]], v;
for (int j = 0; j < n; j++) {
v = Rm[B[j]];
p.push_back(pair<int, int>(tA[u][v], j));
}
sort(p.begin(), p.end(), greater< pair<int, int> >());
for (int j = 0; j < n; j++) {
g.mOrder[i][j] = p[j].second;
// printf("%d ", p[j].second);
}
// puts(" -m");
}
for (int i = 0; i < n; i++) {
vector< pair<int, int> > p;
int u = Rm[B[i]], v;
for (int j = 0; j < n; j++) {
v = Rn[A[j]];
p.push_back(pair<int, int>(tB[u][v], j));
}
sort(p.begin(), p.end(), greater< pair<int, int> >());
for (int j = 0; j < n; j++) {
g.fOrder[i][j] = p[j].second;
// printf("%d ", p[j].second);
}
// puts(" -f");
}
g.stable();
printf("Scenario %d, Mixture %d:\n", cases, ++tcases);
for (int i = 0; i < n; i++) {
int m = g.man[i];
if (i) printf(" ");
printf("%s%s", A[i].c_str(), B[m].c_str());
}
puts("\n");
}
}
return 0;
}
/*
*/