@@ -62,38 +62,52 @@ namespace MaximumBipartiteMatching
62
62
this ->_noOfVertices = newNoOfVertices;
63
63
}
64
64
65
+ // This method is used to color the vertices of the graph to determine if the given graph is bipartite or not
65
66
void Graph::ColorGraph ()
66
67
{
67
68
// Color of all the vertices are initialised to WHITE
68
69
fill (this ->_color .begin (), this ->_color .end (), WHITE);
69
70
71
+ // Queue to hold the vertices
70
72
queue<int > nodeQueue;
71
73
72
74
for (int node = 0 ; node < this ->_noOfVertices ; node++)
73
75
{
76
+ // Check if the node is already not colored
74
77
if (this ->_color [node] == WHITE)
75
78
{
79
+ // The color of the node is set to RED
76
80
this ->_color [node] = RED;
81
+
82
+ // The node is inserted into the queue
77
83
nodeQueue.push (node);
78
84
85
+ // Using BFS method to color all the vertices
79
86
while (!nodeQueue.empty ())
80
87
{
81
88
int nodeU = nodeQueue.front ();
82
89
nodeQueue.pop ();
83
90
91
+ // Iterating over G.Adj[nodeU]
84
92
for (int nodeV = 0 ; nodeV < this ->_noOfVertices ; nodeV++)
85
93
{
94
+ // As there are no self loops, continue
86
95
if (nodeU == nodeV)
87
96
{
88
97
continue ;
89
98
}
99
+ // Check if there is an edge u --> v and nodeV is not colored yet
90
100
else if (this ->_residualGraph [nodeU][nodeV] != 0 && this ->_color [nodeV] == WHITE)
91
101
{
102
+ // Set the color of nodeV opposite of nodeU
92
103
this ->_color [nodeV] = 1 - this ->_color [nodeU];
104
+ // Insert the nodeV into the queue
93
105
nodeQueue.push (nodeV);
94
106
}
107
+ // Check if there is an edge u --> v and nodeV is of same color as nodeU
95
108
else if (this ->_residualGraph [nodeU][nodeV] != 0 && this ->_color [nodeV] == this ->_color [nodeU])
96
109
{
110
+ // Set the _isBipartite flag to false and return
97
111
this ->_isBipartite = false ;
98
112
return ;
99
113
}
@@ -102,33 +116,46 @@ namespace MaximumBipartiteMatching
102
116
}
103
117
}
104
118
119
+ // If the above operation completes without returning yet that indicates the graph is bipartite
120
+ // Set the _isBipartite flag to true and return
105
121
this ->_isBipartite = true ;
106
122
return ;
107
123
}
108
124
125
+ // This method is used to create the additional edges
126
+ // from the source vertex to the RED colored vertices and
127
+ // from the BLUE colored vertices to the sink vertex
109
128
void Graph::AddAdditionalEdges ()
110
129
{
130
+ // Resizing the residual graph to accomodate space for the new edges
111
131
for (auto & edge : this ->_residualGraph )
112
132
{
113
133
edge.resize (this ->_noOfVertices , 0 );
114
134
}
135
+
115
136
this ->_parent .resize (this ->_noOfVertices , -1 );
116
137
this ->_visited .resize (this ->_noOfVertices , false );
117
138
this ->_color .resize (this ->_noOfVertices , WHITE);
118
139
this ->_residualGraph .resize (this ->_noOfVertices , vector<int >(this ->_noOfVertices , 0 ));
140
+
141
+ // Creating the additional edges
119
142
for (int node = 0 ; node < this ->_source ; node++)
120
143
{
144
+ // From source vertex --> RED colored vertices
121
145
if (this ->_color [node] == RED)
122
146
{
123
147
this ->_residualGraph [this ->_source ][node] = 1 ;
124
148
}
149
+
150
+ // From BLUE colored vertices --> sink vertex
125
151
else if (this ->_color [node] == BLUE)
126
152
{
127
153
this ->_residualGraph [node][this ->_sink ] = 1 ;
128
154
}
129
155
}
130
156
}
131
157
158
+ // Implementation of BreadthFirstSearch for EdmondsKarp algorithm to find the path from source to sink
132
159
bool Graph::BreadthFirstSearch ()
133
160
{
134
161
// Resetting the visited values
@@ -198,6 +225,8 @@ namespace MaximumBipartiteMatching
198
225
{
199
226
int augmentedPathFlow = 1 ;
200
227
228
+ // No need to find the minimum amount of augmentedPathFlow as like standard EdmondsKarp algorithm
229
+ // as here capacity of each edges is 1
201
230
for (int nodeV = this ->_sink ; nodeV != this ->_source ; nodeV = this ->_parent [nodeV])
202
231
{
203
232
int nodeU = this ->_parent [nodeV];
@@ -210,12 +239,16 @@ namespace MaximumBipartiteMatching
210
239
return this ->_maximumFlow ;
211
240
}
212
241
242
+ // This method is used for finding the matchings
213
243
vector<vector<int >> Graph::GetMatchings ()
214
244
{
215
245
for (int nodeU = 0 ; nodeU < this ->_adjMatrix .size (); nodeU++)
216
246
{
217
247
for (int nodeV = 0 ; nodeV < this ->_adjMatrix .size (); nodeV++)
218
248
{
249
+ // Check if the nodeU and nodeV are not source or sink
250
+ // and there is a flow of 1 unit from nodeU --> nodeV
251
+ // which means nodeU --> nodeV is being used for the maximum flow (maximum matching)
219
252
if ((nodeU != this ->_source || nodeU != this ->_sink || nodeV != this ->_source || nodeV != this ->_sink )
220
253
&&
221
254
(this ->_adjMatrix [nodeU][nodeV] - this ->_residualGraph [nodeU][nodeV]) == 1 )
0 commit comments