Skip to content

Commit ca180c5

Browse files
Update graph_coloring.cpp
1 parent be550cd commit ca180c5

File tree

1 file changed

+155
-61
lines changed

1 file changed

+155
-61
lines changed

backtracking/graph_coloring.cpp

Lines changed: 155 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,42 @@
11
/**
22
* @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)
54
* algorithm
6-
*
75
* @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
1630
*
1731
* @author [Anup Kumar Panwar](https://github.com/AnupKumarPanwar)
1832
* @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)
1936
*/
2037

2138
#include <array> /// for std::array
39+
#include <cassert> /// for assert
2240
#include <iostream> /// for IO operations
2341

2442
/**
@@ -29,101 +47,177 @@ namespace backtracking {
2947
/**
3048
* @namespace graph_coloring
3149
* @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
3351
*/
3452
namespace graph_coloring {
3553
/**
36-
* @brief A utility function to print the solution
54+
* @brief Prints the color assignments for vertices
3755
* @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
3957
*/
4058
template <size_t V>
4159
void printSolution(const std::array<int, V>& color) {
4260
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 << " ";
4563
}
4664
std::cout << "\n";
4765
}
4866

4967
/**
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
5269
* @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
5975
*/
6076
template <size_t V>
6177
bool isSafe(int v, const std::array<std::array<int, V>, V>& graph,
6278
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) {
6581
return false;
6682
}
6783
}
6884
return true;
6985
}
7086

7187
/**
72-
* @brief Recursive utility function to solve m coloring problem
88+
* @brief Recursive function to solve the graph coloring problem
7389
* @tparam V number of vertices in the graph
74-
* @param graph matrix of graph nonnectivity
90+
* @param graph adjacency matrix of the graph
7591
* @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
7995
*/
8096
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) {
8599
if (v == V) {
86-
printSolution<V>(color);
87-
return;
100+
return true;
88101
}
89102

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) {
93104
if (isSafe<V>(v, graph, color, c)) {
94105
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
101110
}
102111
}
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;
103131
}
104132
} // namespace graph_coloring
105133
} // namespace backtracking
106134

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+
107209
/**
108210
* @brief Main function
109-
* @returns 0 on exit
110211
*/
111212
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();
123214

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);
126221

127-
backtracking::graph_coloring::graphColoring<V>(graph, m, color, 0);
128222
return 0;
129223
}

0 commit comments

Comments
 (0)