summaryrefslogtreecommitdiff
path: root/graph/blossom.cpp
diff options
context:
space:
mode:
authormzuenni <michi.zuendorf@gmail.com>2022-06-27 17:19:28 +0200
committermzuenni <michi.zuendorf@gmail.com>2022-06-27 17:19:28 +0200
commit5ab8a5088b729a9953b8dff1b2a985dc8fb2098b (patch)
treeed40d6936c0e9eee40ba62751cbf99ecddbaddc2 /graph/blossom.cpp
parentadabbad9c51cf7cd3874bfde8eac1fbcf84fec10 (diff)
updated tcr
Diffstat (limited to 'graph/blossom.cpp')
-rw-r--r--graph/blossom.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/graph/blossom.cpp b/graph/blossom.cpp
new file mode 100644
index 0000000..cc19a2b
--- /dev/null
+++ b/graph/blossom.cpp
@@ -0,0 +1,84 @@
+struct GM {
+ vector<vector<int>> adjlist;
+ // pairs ist der gematchte knoten oder n
+ vector<int> pairs, first, que;
+ vector<pair<int, int>> label;
+ int head, tail;
+
+ GM(int n) : adjlist(n), pairs(n + 1, n), first(n + 1, n),
+ que(n), label(n + 1, {-1, -1}) {}
+
+ void rematch(int v, int w) {
+ int t = pairs[v]; pairs[v] = w;
+ if (pairs[t] != v) return;
+ if (label[v].second == -1) {
+ pairs[t] = label[v].first;
+ rematch(pairs[t], t);
+ } else {
+ int x = label[v].first;
+ int y = label[v].second;
+ rematch(x, y);
+ rematch(y, x);
+ }}
+
+ int findFirst(int u) {
+ return label[first[u]].first < 0 ? first[u]
+ : first[u] = findFirst(first[u]);
+ }
+
+ void relabel(int x, int y) {
+ int r = findFirst(x);
+ int s = findFirst(y);
+ if (r == s) return;
+ auto h = label[r] = label[s] = {~x, y};
+ int join;
+ while (true) {
+ if (s != sz(adjlist)) swap(r, s);
+ r = findFirst(label[pairs[r]].first);
+ if (label[r] == h) {
+ join = r;
+ break;
+ } else {
+ label[r] = h;
+ }}
+ for (int v : {first[x], first[y]}) {
+ for (; v != join; v = first[label[pairs[v]].first]) {
+ label[v] = {x, y};
+ first[v] = join;
+ que[tail++] = v;
+ }}}
+
+ bool augment(int u) {
+ label[u] = {sz(adjlist), -1};
+ first[u] = sz(adjlist);
+ head = tail = 0;
+ for (que[tail++] = u; head < tail;) {
+ int x = que[head++];
+ for (int y : adjlist[x]) {
+ if (pairs[y] == sz(adjlist) && y != u) {
+ pairs[y] = x;
+ rematch(x, y);
+ return true;
+ } else if (label[y].first >= 0) {
+ relabel(x, y);
+ } else if (label[pairs[y]].first == -1) {
+ label[pairs[y]].first = x;
+ first[pairs[y]] = y;
+ que[tail++] = pairs[y];
+ }}}
+ return false;
+ }
+
+ int match() {
+ int matching = head = tail = 0;
+ for (int u = 0; u < sz(adjlist); u++) {
+ if (pairs[u] < sz(adjlist) || !augment(u)) continue;
+ matching++;
+ for (int i = 0; i < tail; i++)
+ label[que[i]] = label[pairs[que[i]]] = {-1, -1};
+ label[sz(adjlist)] = {-1, -1};
+ }
+ return matching;
+ }
+
+}; \ No newline at end of file