forked from t3nsor/codebook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeneral-matching.cpp
101 lines (96 loc) · 2.24 KB
/
general-matching.cpp
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
// Unweighted general matching.
// Vertices are numbered from 1 to V.
// G is an adjlist.
// G[x][0] contains the number of neighbours of x.
// The neigbours are then stored in G[x][1] ..
// G[x][G[x][0]]. Mate[x] will contain the matching node for
// x. V and E are the number of edges and vertices. Slow
// Version (2x on random graphs) of Gabow's implementation
// of Edmonds' algorithm (O(V^3)).
const int MAXV = 250;
int G[MAXV][MAXV];
int VLabel[MAXV];
int Queue[MAXV];
int Mate[MAXV];
int Save[MAXV];
int Used[MAXV];
int Up, Down;
int V;
void ReMatch(int x, int y) {
int m = Mate[x];
Mate[x] = y;
if (Mate[m] == x) {
if (VLabel[x] <= V) {
Mate[m] = VLabel[x];
ReMatch(VLabel[x], m);
} else {
int a = 1 + (VLabel[x] - V - 1) / V;
int b = 1 + (VLabel[x] - V - 1) % V;
ReMatch(a, b);
ReMatch(b, a);
}
}
}
void Traverse(int x) {
for (int i = 1; i <= V; i++)
Save[i] = Mate[i];
ReMatch(x, x);
for (int i = 1; i <= V; i++) {
if (Mate[i] != Save[i])
Used[i]++;
Mate[i] = Save[i];
}
}
void ReLabel(int x, int y) {
for (int i = 1; i <= V; i++)
Used[i] = 0;
Traverse(x);
Traverse(y);
for (int i = 1; i <= V; i++) {
if (Used[i] == 1 && VLabel[i] < 0) {
VLabel[i] = V + x + (y - 1) * V;
Queue[Up++] = i;
}
}
}
// Call this after constructing G
void Solve() {
for (int i = 1; i <= V; i++)
if (Mate[i] == 0) {
for (int j = 1; j <= V; j++)
VLabel[j] = -1;
VLabel[i] = 0;
Down = 1;
Up = 1;
Queue[Up++] = i;
while (Down != Up) {
int x = Queue[Down++];
for (int p = 1; p <= G[x][0]; p++) {
int y = G[x][p];
if (Mate[y] == 0 && i != y) {
Mate[y] = x;
ReMatch(x, y);
Down = Up;
break;
}
if (VLabel[y] >= 0) {
ReLabel(x, y);
continue;
}
if (VLabel[Mate[y]] < 0) {
VLabel[Mate[y]] = x;
Queue[Up++] = Mate[y];
}
}
}
}
}
// Call this after Solve(). Returns number of edges in
// matching (half the number of matched vertices)
int Size() {
int Count = 0;
for (int i = 1; i <= V; i++)
if (Mate[i] > i)
Count++;
return Count;
}