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