1
1
/* *
2
2
* @file
3
- * @brief prints the assigned colors
4
- * using [Graph Coloring](https://en.wikipedia.org/wiki/Graph_coloring)
3
+ * @brief [Graph Coloring](https://en.wikipedia.org/wiki/Graph_coloring)
5
4
* algorithm
6
- *
7
5
* @details
8
- * In graph theory, graph coloring is a special case of graph labeling;
9
- * it is an assignment of labels traditionally called "colors" to elements of a
10
- * graph subject to certain constraints. In its simplest form, it is a way of
11
- * coloring the vertices of a graph such that no two adjacent vertices are of
12
- * the same color; this is called a vertex coloring. Similarly, an edge coloring
13
- * assigns a color to each edge so that no two adjacent edges are of the same
14
- * color, and a face coloring of a planar graph assigns a color to each face or
15
- * region so that no two faces that share a boundary have the same color.
6
+ * Graph coloring assigns colors to vertices of a graph such that no two
7
+ * adjacent vertices share the same color. This implementation uses backtracking
8
+ * to find a valid coloring for a given graph and number of colors (m). It is
9
+ * useful for problems like scheduling, map coloring, and register allocation.
10
+ *
11
+ * ### Algorithm
12
+ * 1. Start with vertex 0, assign colors from 1 to m.
13
+ * 2. Check if a color is safe for a vertex (no adjacent vertex has the same
14
+ * color).
15
+ * 3. If safe, assign the color and recurse to the next vertex.
16
+ * 4. If all vertices are colored, a solution is found.
17
+ * 5. Backtrack if no valid color works for a vertex.
18
+ *
19
+ * ### Complexity
20
+ * - Time: O(m^V) worst-case (exponential, m=colors, V=vertices)
21
+ * - Space: O(V) for recursion stack and color array
22
+ *
23
+ * ### Example
24
+ * For graph: (3)---(2)
25
+ * | / |
26
+ * | / |
27
+ * | / |
28
+ * (0)---(1)
29
+ * With 3 colors: Possible coloring: 1 2 3 2
16
30
*
17
31
* @author [Anup Kumar Panwar](https://github.com/AnupKumarPanwar)
18
32
* @author [David Leal](https://github.com/Panquesito7)
33
+ * @author [Contributor] (fix Test 5 for 2-colorable disconnected graph)
34
+ * @author [Contributor] (added Add comprehensive test cases for backtracking
35
+ * algorithms)(https://github.com/kokatesaurabh)
19
36
*/
20
37
21
38
#include < array> // / for std::array
39
+ #include < cassert> // / for assert
22
40
#include < iostream> // / for IO operations
23
41
24
42
/* *
@@ -29,101 +47,177 @@ namespace backtracking {
29
47
/* *
30
48
* @namespace graph_coloring
31
49
* @brief Functions for the [Graph
32
- * Coloring](https://en.wikipedia.org/wiki/Graph_coloring) algorithm,
50
+ * Coloring](https://en.wikipedia.org/wiki/Graph_coloring) algorithm
33
51
*/
34
52
namespace graph_coloring {
35
53
/* *
36
- * @brief A utility function to print the solution
54
+ * @brief Prints the color assignments for vertices
37
55
* @tparam V number of vertices in the graph
38
- * @param color array of colors assigned to the nodes
56
+ * @param color array of colors assigned to vertices
39
57
*/
40
58
template <size_t V>
41
59
void printSolution (const std::array<int , V>& color) {
42
60
std::cout << " Following are the assigned colors\n " ;
43
- for (auto & col : color) {
44
- std::cout << col;
61
+ for (const auto & col : color) {
62
+ std::cout << col << " " ;
45
63
}
46
64
std::cout << " \n " ;
47
65
}
48
66
49
67
/* *
50
- * @brief Utility function to check if the current color assignment is safe for
51
- * vertex v
68
+ * @brief Checks if assigning color c to vertex v is safe
52
69
* @tparam V number of vertices in the graph
53
- * @param v index of graph vertex to check
54
- * @param graph matrix of graph nonnectivity
55
- * @param color vector of colors assigned to the graph nodes/vertices
56
- * @param c color value to check for the node `v`
57
- * @returns `true` if the color is safe to be assigned to the node
58
- * @returns `false` if the color is not safe to be assigned to the node
70
+ * @param v index of the vertex to check
71
+ * @param graph adjacency matrix of the graph
72
+ * @param color array of colors assigned to vertices
73
+ * @param c color to check for vertex v
74
+ * @returns true if the color is safe, false otherwise
59
75
*/
60
76
template <size_t V>
61
77
bool isSafe (int v, const std::array<std::array<int , V>, V>& graph,
62
78
const std::array<int , V>& color, int c) {
63
- for (int i = 0 ; i < V; i++ ) {
64
- if (graph[v][i] && c == color[i]) {
79
+ for (int i = 0 ; i < V; ++i ) {
80
+ if (graph[v][i] && color[i] == c ) {
65
81
return false ;
66
82
}
67
83
}
68
84
return true ;
69
85
}
70
86
71
87
/* *
72
- * @brief Recursive utility function to solve m coloring problem
88
+ * @brief Recursive function to solve the graph coloring problem
73
89
* @tparam V number of vertices in the graph
74
- * @param graph matrix of graph nonnectivity
90
+ * @param graph adjacency matrix of the graph
75
91
* @param m number of colors
76
- * @param [in,out] color description // used in,out to notify in documentation
77
- * that this parameter gets modified by the function
78
- * @param v index of graph vertex to check
92
+ * @param color array to store colors assigned to vertices
93
+ * @param v current vertex index
94
+ * @returns true if a valid coloring is found, false otherwise
79
95
*/
80
96
template <size_t V>
81
- void graphColoring (const std::array<std::array<int , V>, V>& graph, int m,
82
- std::array<int , V> color, int v) {
83
- // base case:
84
- // If all vertices are assigned a color then return true
97
+ bool graphColoringUtil (const std::array<std::array<int , V>, V>& graph, int m,
98
+ std::array<int , V>& color, int v) {
85
99
if (v == V) {
86
- printSolution<V>(color);
87
- return ;
100
+ return true ;
88
101
}
89
102
90
- // Consider this vertex v and try different colors
91
- for (int c = 1 ; c <= m; c++) {
92
- // Check if assignment of color c to v is fine
103
+ for (int c = 1 ; c <= m; ++c) {
93
104
if (isSafe<V>(v, graph, color, c)) {
94
105
color[v] = c;
95
-
96
- // recur to assign colors to rest of the vertices
97
- graphColoring<V>(graph, m, color, v + 1 );
98
-
99
- // If assigning color c doesn't lead to a solution then remove it
100
- color[v] = 0 ;
106
+ if (graphColoringUtil<V>(graph, m, color, v + 1 )) {
107
+ return true ;
108
+ }
109
+ color[v] = 0 ; // Backtrack
101
110
}
102
111
}
112
+ return false ;
113
+ }
114
+
115
+ /* *
116
+ * @brief Solves the graph coloring problem
117
+ * @tparam V number of vertices in the graph
118
+ * @param graph adjacency matrix of the graph
119
+ * @param m number of colors
120
+ * @returns true if a valid coloring exists, false otherwise
121
+ */
122
+ template <size_t V>
123
+ bool graphColoring (const std::array<std::array<int , V>, V>& graph, int m) {
124
+ std::array<int , V> color{};
125
+ if (!graphColoringUtil<V>(graph, m, color, 0 )) {
126
+ std::cout << " Solution does not exist\n " ;
127
+ return false ;
128
+ }
129
+ printSolution<V>(color);
130
+ return true ;
103
131
}
104
132
} // namespace graph_coloring
105
133
} // namespace backtracking
106
134
135
+ /* *
136
+ * @brief Self-test implementations for graph coloring
137
+ */
138
+ static void test () {
139
+ std::cout << " Running comprehensive graph coloring tests...\n " ;
140
+
141
+ // Test 1: Basic 4-vertex graph with 3 colors
142
+ {
143
+ const int V = 4 ;
144
+ std::array<std::array<int , V>, V> graph1 = {
145
+ {{{0 , 1 , 1 , 1 }}, {{1 , 0 , 1 , 0 }}, {{1 , 1 , 0 , 1 }}, {{1 , 0 , 1 , 0 }}}};
146
+ assert (backtracking::graph_coloring::graphColoring<V>(graph1, 3 ) ==
147
+ true );
148
+ std::cout << " Test 1 passed\n " ;
149
+ }
150
+
151
+ // Test 2: Complete graph K4 with 4 colors
152
+ {
153
+ const int V = 4 ;
154
+ std::array<std::array<int , V>, V> graph2 = {
155
+ {{{0 , 1 , 1 , 1 }}, {{1 , 0 , 1 , 1 }}, {{1 , 1 , 0 , 1 }}, {{1 , 1 , 1 , 0 }}}};
156
+ assert (backtracking::graph_coloring::graphColoring<V>(graph2, 4 ) ==
157
+ true );
158
+ std::cout << " Test 2 passed\n " ;
159
+ }
160
+
161
+ // Test 3: Triangle graph with 2 colors (no solution)
162
+ {
163
+ const int V = 3 ;
164
+ std::array<std::array<int , V>, V> graph3 = {
165
+ {{{0 , 1 , 1 }}, {{1 , 0 , 1 }}, {{1 , 1 , 0 }}}};
166
+ assert (backtracking::graph_coloring::graphColoring<V>(graph3, 2 ) ==
167
+ false );
168
+ std::cout << " Test 3 passed\n " ;
169
+ }
170
+
171
+ // Test 4: Single vertex graph with 1 color
172
+ {
173
+ const int V = 1 ;
174
+ std::array<std::array<int , V>, V> graph4 = {{{{0 }}}};
175
+ assert (backtracking::graph_coloring::graphColoring<V>(graph4, 1 ) ==
176
+ true );
177
+ std::cout << " Test 4 passed\n " ;
178
+ }
179
+
180
+ // Test 5: Disconnected 2-colorable graph
181
+ {
182
+ const int V = 5 ;
183
+ std::array<std::array<int , V>, V> graph5 = {{{{0 , 1 , 0 , 0 , 0 }},
184
+ {{1 , 0 , 0 , 0 , 0 }},
185
+ {{0 , 0 , 0 , 1 , 0 }},
186
+ {{0 , 0 , 1 , 0 , 0 }},
187
+ {{0 , 0 , 0 , 0 , 0 }}}};
188
+ assert (backtracking::graph_coloring::graphColoring<V>(graph5, 2 ) ==
189
+ true );
190
+ std::cout << " Test 5 passed\n " ;
191
+ }
192
+
193
+ // Test 6: Star graph with 2 colors
194
+ {
195
+ const int V = 5 ;
196
+ std::array<std::array<int , V>, V> graph6 = {{{{0 , 1 , 1 , 1 , 1 }},
197
+ {{1 , 0 , 0 , 0 , 0 }},
198
+ {{1 , 0 , 0 , 0 , 0 }},
199
+ {{1 , 0 , 0 , 0 , 0 }},
200
+ {{1 , 0 , 0 , 0 , 0 }}}};
201
+ assert (backtracking::graph_coloring::graphColoring<V>(graph6, 2 ) ==
202
+ true );
203
+ std::cout << " Test 6 passed\n " ;
204
+ }
205
+
206
+ std::cout << " All tests passed successfully!\n\n " ;
207
+ }
208
+
107
209
/* *
108
210
* @brief Main function
109
- * @returns 0 on exit
110
211
*/
111
212
int main () {
112
- // Create following graph and test whether it is 3 colorable
113
- // (3)---(2)
114
- // | / |
115
- // | / |
116
- // | / |
117
- // (0)---(1)
118
-
119
- const int V = 4 ; // number of vertices in the graph
120
- std::array<std::array<int , V>, V> graph = {
121
- std::array<int , V>({0 , 1 , 1 , 1 }), std::array<int , V>({1 , 0 , 1 , 0 }),
122
- std::array<int , V>({1 , 1 , 0 , 1 }), std::array<int , V>({1 , 0 , 1 , 0 })};
213
+ test ();
123
214
124
- int m = 3 ; // Number of colors
125
- std::array<int , V> color{};
215
+ std::cout << " Demo graph:\n " ;
216
+ const int V = 4 ;
217
+ std::array<std::array<int , V>, V> graph = {
218
+ {{{0 , 1 , 1 , 1 }}, {{1 , 0 , 1 , 0 }}, {{1 , 1 , 0 , 1 }}, {{1 , 0 , 1 , 0 }}}};
219
+ int m = 3 ;
220
+ backtracking::graph_coloring::graphColoring<V>(graph, m);
126
221
127
- backtracking::graph_coloring::graphColoring<V>(graph, m, color, 0 );
128
222
return 0 ;
129
223
}
0 commit comments