-
Notifications
You must be signed in to change notification settings - Fork 1
/
Blossom.cpp
137 lines (119 loc) · 3.67 KB
/
Blossom.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <bits/stdc++.h>
using namespace std;
struct Blossom {
/**
0 based indexing
complexity - O(VE)
**/
const int MAXN = 500 + 5; // number of elements.
vector < vector <int> > g;
vector <int> match;
vector <int> p; //array of ancestors.
vector <int> base; //Node numbering after compression
vector <int> q; /*Queue*/
vector <bool> used;
vector <bool> blossom;
int n; //number of nodes
Blossom(int n): n(n), g(n, vector <int> ()), match(n, -1), p(n), base(n), q(n), used(n), blossom(n, false) {
}
void add_edge(int u, int v) {
g[u].push_back(v);
g[v].push_back(u);
}
int lca(int a, int b) {
vector <bool> usedInternal(n, false);
// From the node a climb up to the roots, marking all even vertices
for (;;) {
a = base[a];
usedInternal[a] = true;
if (match[a] == -1) break; /* Got the root */
a = p[match[a]];
}
// Climb from node b,until we find the marked vertex
for (;;) {
b = base[b];
if (usedInternal[b]) return b;
b = p[match[b]];
}
}
void mark_path(int v, int b, int children) {
while (base[v] != b) {
blossom[base[v]] = blossom[base[match[v]]] = true;
p[v] = children;
children = match[v];
v = p[match[v]];
}
}
int find_path(int root) {
used = vector <bool> (n, false);
p = vector <int> (n, -1);
for (int i = 0; i < n; ++i) base[i] = i;
used[root] = true;
int qh = 0, qt = 0;
q[qt++] = root;
while (qh < qt) {
int v = q[qh++];
for (int i=0; i < g[v].size(); ++i) {
int to = g[v][i];
if (base[v] == base[to] || match[v] == to) continue;
if (to == root || match[to] != -1 && p[match[to]] != -1) {
int curbase = lca(v, to);
blossom = vector <bool> (n, false);
mark_path(v, curbase, to);
mark_path(to, curbase, v);
for (int i = 0; i < n; ++i)
if (blossom[base[i]]) {
base[i] = curbase;
if (!used[i]) {
used[i] = true;
q[qt++] = i;
}
}
} else if (p[to] == -1) {
p[to] = v;
if (match[to] == -1) return to;
to = match[to];
used[to] = true;
q[qt++] = to;
}
}
}
return -1;
}
int graph_match() {
int ret = 0;
for (int i = 0; i < n; ++i)
if (match[i] == -1) {
int v = find_path(i);
if(v != -1) ret++;
while (v != -1) {
int pv = p[v], ppv = match[pv];
match[v] = pv, match[pv] = v;
v = ppv;
}
}
return ret;
}
/**
Tested Problems: SEAGRP(Code Chef), Work Scheduling(Timus)
**/
};
int main() {
ios_base::sync_with_stdio(false);
int n, m;
cin >> n >> m;
Blossom graph(n);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
u--, v--;
graph.add_edge(u, v);
}
int ans = graph.graph_match();
cout << 2 * ans << endl;
for (int i = 0; i < graph.n; i++)
if (graph.match[i] > -1) {
cout << i + 1 << ' ' << graph.match[i] + 1 << endl;
}
return 0;
}