1 module dkh.graph.bipatitematching;
2 
3 struct BipatiteMatching {
4     import std.conv : to;
5     int L, R, count;
6     int[][] g;
7     int[] lmt, rmt;
8     int[] visited; int vc;
9     this(size_t L, size_t R) {
10         this.L = L.to!int; this.R = R.to!int;
11         g = new int[][L];
12         visited = new int[L];
13         lmt = new int[L]; lmt[] = -1;
14         rmt = new int[R]; rmt[] = -1;
15     }
16     bool dfs(int l) {
17         if (l == -1) return true;
18         if (visited[l] == vc) return false;
19         visited[l] = vc;
20         foreach (r; g[l]) {
21             if (dfs(rmt[r])) {
22                 lmt[l] = r;
23                 rmt[r] = l;
24                 return true;
25             }
26         }
27         return false;
28     }
29     void maximize() {
30         vc++;
31         foreach (i; 0..L) {
32             if (lmt[i] != -1) continue;
33             if (g[i].length == 0) continue;
34             if (dfs(i)) count++;
35         }
36     }
37     /// add edge(l, r)
38     void addEdge(size_t l, size_t r) {
39         g[l] ~= r.to!int;
40         maximize();
41     }
42     /// del edge(l, r)
43     void delEdge(size_t l, size_t r) {
44         import std.algorithm : remove;
45         g[l] = g[l].remove!(a => a == r.to!int);
46         if (rmt[r] == l.to!int) {
47             count--;
48             lmt[l] = rmt[r] = -1;
49             maximize();
50         }
51     }
52     /// cng left_l's edge
53     void cngLeftVertexEdge(size_t l, in int[] v) {
54         g[l] = v.dup;
55         vc++;
56         if (lmt[l] == -1) {
57             if (dfs(l.to!int)) count++;
58         } else {
59             count--;
60             int r = lmt[l];
61             lmt[l] = rmt[r] = -1;
62             maximize();
63         }
64     }
65 }
66 
67 ///
68 unittest {
69     auto bm = BipatiteMatching(3, 3);
70     bm.addEdge(0, 0);
71     bm.addEdge(0, 1);
72     bm.addEdge(1, 1);
73     bm.addEdge(2, 1);
74     assert(bm.count == 2); // example: (0, 0), (1, 1)
75     bm.addEdge(1, 2);
76     assert(bm.count == 3); // (0, 0), (1, 2), (2, 1)
77     bm.delEdge(2, 1);
78     assert(bm.count == 2); // example: (0, 0) (1, 2)
79 }