Worldscope

Vertex coloring in Graph theory

Palavras-chave:

Publicado em: 31/08/2025

Vertex Coloring in Graph Theory

Vertex coloring is a fundamental concept in graph theory, where the goal is to assign colors to the vertices of a graph such that no two adjacent vertices share the same color. This article explores vertex coloring, focusing on a practical implementation using a greedy approach. We will provide a well-commented code example, analyze its complexity, and discuss alternative strategies.

Fundamental Concepts / Prerequisites

Before diving into the implementation, it's essential to have a basic understanding of the following:

  • Graph: A graph consists of a set of vertices (nodes) and a set of edges connecting these vertices.
  • Adjacency: Two vertices are adjacent if they are connected by an edge.
  • Vertex Coloring: Assigning colors to vertices such that no two adjacent vertices have the same color.
  • Chromatic Number: The minimum number of colors required to color a graph.
  • Greedy Algorithm: An algorithm that makes locally optimal choices at each step with the hope of finding a global optimum.

We will represent the graph using an adjacency list.

Implementation in Python


def graph_coloring(graph):
    """
    Colors the vertices of a graph using a greedy algorithm.

    Args:
        graph (dict): A dictionary representing the graph as an adjacency list.
                      Keys are vertices, and values are lists of adjacent vertices.

    Returns:
        dict: A dictionary mapping vertices to their assigned colors (integers).
              Returns None if the graph is empty.
    """

    if not graph:
        return None

    coloring = {}  # Dictionary to store the color assigned to each vertex
    available_colors = set() #Set of colors that can be used

    # Iterate through the vertices
    for vertex in graph:
        available_colors.clear()
        # Find the colors used by the neighbors of the current vertex
        used_colors = set()
        for neighbor in graph[vertex]:
            if neighbor in coloring:
                used_colors.add(coloring[neighbor])

        # Find the first available color that is not used by any neighbor
        color = 1  # Start with color 1
        while color in used_colors:
            color += 1

        # Assign the found color to the current vertex
        coloring[vertex] = color

    return coloring

# Example Usage
if __name__ == "__main__":
    graph = {
        'A': ['B', 'C'],
        'B': ['A', 'C', 'D'],
        'C': ['A', 'B', 'D'],
        'D': ['B', 'C']
    }

    coloring = graph_coloring(graph)

    if coloring:
        print("Vertex Coloring:")
        for vertex, color in coloring.items():
            print(f"Vertex {vertex}: Color {color}")
    else:
        print("The graph is empty.")

Code Explanation

The `graph_coloring` function takes an adjacency list representation of a graph as input.

1. **Initialization:** It initializes an empty dictionary `coloring` to store the color assigned to each vertex. It also creates a set to store the colors available.

2. **Iterating through vertices:** It iterates through each vertex in the graph.

3. **Finding used colors:** For each vertex, it identifies the colors already used by its neighbors by checking the `coloring` dictionary.

4. **Finding available color:** It starts with color 1 and increments it until it finds a color that is not present in the `used_colors` set.

5. **Assigning color:** It assigns the found `color` to the current `vertex` in the `coloring` dictionary.

6. **Returning coloring:** Finally, it returns the `coloring` dictionary, which maps each vertex to its assigned color. The `main` section showcases how to create a sample graph and invoke the algorithm.

Complexity Analysis

Time Complexity: In the worst-case scenario, for each vertex, the algorithm might have to check all previously assigned colors to find an available color. If 'n' is the number of vertices and 'm' is the maximum degree of a vertex (maximum number of neighbors), the time complexity for each vertex is O(m). Therefore, the overall time complexity is O(n*m). In a dense graph, `m` could be close to `n`, leading to O(n^2).

Space Complexity: The space complexity is primarily determined by the `coloring` dictionary, which stores the color assignment for each vertex, taking O(n) space. The `used_colors` set will, at most, contain the number of adjacent vertices. Therefore, the space complexity is O(n).

Alternative Approaches

One alternative approach is to use a more sophisticated algorithm like backtracking or a more advanced greedy algorithm with ordering heuristics (e.g., Welsh-Powell algorithm, which orders vertices by degree). Backtracking guarantees finding the optimal coloring (minimum number of colors) but has exponential time complexity. The Welsh-Powell algorithm improves on the basic greedy approach by ordering vertices by degree, often leading to better (though not necessarily optimal) colorings compared to random orderings.

Conclusion

Vertex coloring is a core concept in graph theory with various applications. The greedy algorithm presented here provides a simple and relatively efficient way to color a graph, although it doesn't guarantee the optimal solution (minimum number of colors). Understanding the time and space complexity, along with alternative approaches, allows developers to choose the most appropriate algorithm for their specific needs.