Graph Coloring(๊ทธ๋ž˜ํ”„ ์ฑ„์ƒ‰)

2011. 12. 23. 12:47ยทAlgorithms/Backtracking

Basic Concept


The m-Coloring problem concerns finding all ways to color an undirected graph using at most m different colors, so that no two adjacent vertices are the same color. We usually call the m-Coloring problem a unique problem for each value of m. An important application of graph coloring is the coloring of maps.

 

๐Ÿ‘‰ m-๊ทธ๋ž˜ํ”„ ์ฑ„์ƒ‰ ๋ฌธ์ œ๋Š” ๋น„๋ฐฉํ–ฅ๊ทธ๋ž˜ํ”„์—์„œ ์„œ๋กœ ์ธ์ ‘ํ•œ ์ •์ ์ด ๊ฐ™์€ ์ƒ‰์„ ๊ฐ–์ง€ ์•Š๋„๋ก ์ตœ๋Œ€ m๊ฐœ์˜ ๋‹ค๋ฅธ ์ƒ‰์œผ๋กœ ์น ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋‘ ์ฐพ๋Š” ๊ฒƒ์ด๋‹ค. m๊ฐ’์— ๋Œ€ํ•ด์„œ๋Š” ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋ฌธ์ œ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค. ๊ทธ๋ž˜ํ”„ ์ฑ„์ƒ‰์˜ ์ค‘์š”ํ•œ ์‘์šฉ์€ ์ง€๋„์˜ ์ฑ„์ƒ‰์ด๋‹ค.

 

A graph is called planar if it can be drawn in a plane in such a way that no two edges cross each other. The graph at the below is planar. However, if we were to add the edges ($v_1$, $v_5$) and ($v_2$, $v_4$) it would no longer be planar. To every map there corresponds a planar graph. Each region in the map is represented by a vertex. If one region is adjacent to another region, we join their corresponding vertices by an edge. The below figure shows a map at the left and its planar graph representation at the right.

 

[Map(left) and its planar graph representation(right)]

๐Ÿ‘‰ 2๊ฐœ์˜ ์ด์Œ์„ ์ด ์„œ๋กœ ๊ต์ฐจํ•˜์ง€ ์•Š๋„๋ก ๊ทธ๋ฆฐ ๊ทธ๋ž˜ํ”„๋ฅผ ํ‰๋ฉด๊ทธ๋ž˜ํ”„๋ผ๊ณ  ํ•œ๋‹ค. ๋ชจ๋“  ์ง€๋„๋Š” ๊ทธ์— ์ƒ์‘ํ•˜๋Š” ํ‰๋ฉด๊ทธ๋ž˜ํ”„๋กœ ๋ฐ”๊ฟ” ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ์ง€๋„์—์„œ ๊ฐ ์ง€์—ญ์€ ์ •์ ์— ํ•ด๋‹นํ•œ๋‹ค. ๋งŒ์ผ ํ•œ ์ง€์—ญ์ด ๋‹ค๋ฅธ ์ง€์—ญ๊ณผ ์ธ์ ‘ํ•ด ์žˆ์œผ๋ฉด, ๊ทธ ์ •์ ๋“ค์„ ์ด์Œ์„ ์œผ๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค.

 

Example There is no solution to the 2-Coloring problem for this graph because, if we can use at most two different colors, there is no way to color the vertices so that no adjacent vertices are the same color. One solution to the 3-Coloring problem for this graph is as follows:

 

$$ \begin{align} Ve&rtex  &Color \notag{}\\ &v_1  &color1 \notag{} \\ &v_2  &color2 \notag{} \\ &v_3  &color3 \notag{} \\ &v_4  &color4 \notag{} \end{align} $$

 

There are a total of six solutions to the 3-Coloring problem for this graph. However, the six solutions are only different in the way the colors are permuted. For example, another solution is to color $v_1$ color 2, $v_2$ and $v_4$ color 1, and $v_3$ color 3.

 

๐Ÿ‘‰ ์œ„์˜ ๊ทธ๋ž˜ํ”„์—์„œ ์ตœ๋Œ€ 2๊ฐœ์˜ ์ƒ‰๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ธ์ ‘ํ•œ ์ •์ ์ด ๊ฐ™์€ ์ƒ‰์„ ๊ฐ–์ง€ ์•Š๋„๋ก ์น ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ์ฆ‰, 2-Coloring ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๋‹ต์€ ์—†๋‹ค.
3๊ฐœ์˜ ๋‹ค๋ฅธ ์ƒ‰์œผ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ์ฑ„์ƒ‰ํ•˜๋Š” ๊ฒฝ์šฐ ์ด 6๊ฐ€์ง€ ํ•ด๋‹ต์ด ์กด์žฌํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ 6๊ฐ€์ง€ ํ•ด๋‹ต์€ ์ƒ‰์ด ์กฐํ•ฉ๋œ ๋ฐฉ๋ฒ•๋งŒ ๋‹ค๋ฅผ ๋ฟ์ด๋‹ค.

 

 

The Backtracking Algorithm for the m-Coloring Problem


Algorithm Design

A straightforward state space tree for the m-Coloring problem is one in which

  • each possible color is tried for vertex $v_1$ at level 1,
  • each possible color is tried for vertex $v_2$ at level 2,
  • and so on until each possible color has been tried for vertex $v_n$ at level n.

Each path from the root to a leaf is a candidate solution. We check whether a candidate solution is a solution by determining whether any two adjacent vertices are the same color.

 

๐Ÿ‘‰ m-Coloring ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ƒํƒœ๊ณต๊ฐ„ํŠธ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ๋ ˆ๋ฒจ 1์—์„œ ์ •์  $v_1$์— ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์ƒ‰์„ ๊ฐ๊ฐ ์‹œ๋„ํ•˜๊ณ , ๋ ˆ๋ฒจ 2์—์„œ๋Š” ์ •์  $v_2$์— ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์ƒ‰์„ ๊ฐ๊ฐ ์‹œ๋„ํ•ด ๋ณธ๋‹ค. ์ด๋Ÿฐ์‹์œผ๋กœ ๋ ˆ๋ฒจ n์—์„œ๋Š” ์ •์  $v_n$์— ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์ƒ‰์„ ๊ฐ๊ฐ ์‹œ๋„ํ•ด ๋ณธ๋‹ค.
์ƒํƒœ๊ณต๊ฐ„ํŠธ๋ฆฌ์˜ ๋ฃจํŠธ๋…ธ๋“œ์—์„œ ์žŽ๋…ธ๋“œ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๊ฐ€ ํ•ด๋‹ตํ›„๋ณด๊ฐ€ ๋˜๋ฉฐ, ์ธ์ ‘ํ•œ ์ •์ ์ด ๊ฐ™์€ ์ƒ‰์ธ์ง€๋ฅผ ๊ฒฐ์ •ํ•จ์œผ๋กœ์จ ํ•ด๋‹ต์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•œ๋‹ค.

 

We can backtrack in this problem because a node is nonpromising if a vertex that is adjacent to the vertex being colored at the node has already been colored the color that is being used at the node. After $v_1$ is colored color 1, choosing color 1 for $v_2$ is nonpromising because $v_1$ is adjacent to $v_2$. Similarly, after $v_1$, $v_2$, and $v_3$ have been colored colors 1, 2, and 3, respectively, choosing color 1 for $v_4$ is nonpromising because $v_1$ is adjacent to $v_4$.

 

๐Ÿ‘‰ ํ•œ ์ •์ ์—์„œ ์‚ฌ์šฉ๋œ ์ƒ‰์ด ์ธ์ ‘ํ•œ ์ •์ ์„ ์น ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋๋‹ค๋ฉด ๊ทธ ๋งˆ๋””๋Š” ์œ ๋งํ•˜์ง€ ์•Š๋‹ค. ์ด ์ ์„ ์ด์šฉํ•˜๋ฉด ์ด๋ฒˆ ๋ฌธ์ œ์—์„œ๋„ ๋ฐฑํŠธ๋ž˜ํ‚น์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, $v_1$์„ ์ƒ‰1๋กœ ์น ํ•œ ํ›„ $v_2$์—์„œ ์ƒ‰1์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์€ ์œ ๋งํ•˜์ง€ ์•Š๋‹ค. $v_1$๊ณผ $v_2$๋Š” ์„œ๋กœ ์ธ์ ‘ํ•ด์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ $v_1$, $v_2$, $v_3$๋ฅผ ์ƒ‰1, ์ƒ‰2, ์ƒ‰3์œผ๋กœ ์น ํ•œ ๊ฒฝ์šฐ $v_4$์—์„œ ์ƒ‰1์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์€ ์œ ๋งํ•˜์ง€ ์•Š๋‹ค.

 

In this algorithm the graph is represented by an adjacency matrix. However, because the graph is unweighted, each entry in the matrix is simply true or false depending on whether or not there is an edge between the two vertices.

 

๐Ÿ‘‰ ์ด๋ฒˆ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ž…๋ ฅ๊ฐ’์œผ๋กœ ๋น„๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ ์ž๋ฃŒ๊ตฌ์กฐ(์ธ์ ‘ํ–‰๋ ฌ๋กœ ํ‘œํ˜„)๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค. ๋น„๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ์ •์  ๊ฐ„ ์ด์Œ์„ ์ด ์žˆ๋‹ค๋ฉด True, ์—†๋‹ค๋ฉด False๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. 

 

Pseudo Code

  • The Backtracking Algorithm for the m-Coloring Problem
void m_coloring(index i)
{
  int color;

  if (promising(i))
    if (i == n)
      cout << vcolor[1] through vcolor[n];
    else
      for (color = 1; color <= m; color++) {
        vcolor[i+1] = color;
        m_coloring(i+1);
      }
}

bool promising(index i)
{
  index j;
  bool switch;

  switch = true;
  j = 1;
  while (j < i && switch) {
    if (W[i][j] && vcolor[i] == vcolor[j])
      switch = false;
    j++;
  }
  return switch;
}

 

Source Code

  • mcoloring.h
// File: mcoloring.h
#ifndef GRAPH_COLOR_H
#define GRAPH_COLOR_H
#include "graph.h"
using namespace data_structures; // for graph

namespace algorithms
{  
  void m_coloring(graph g, int i, int* vcolor);
  // Problem: Determine all ways in which the vertices in an undirected graph can
  // be colored, using only m colors, so that adjacent vertices are not the same
  // color.
  // Inputs: positive integers n and m, and an undirected graph containing
  // n vertices. The graph is represented by a two-dimensional array W, which
  // has both its rows and columns indexed from 1 to n, where W [i][j] is true if
  // there is an edge between ith vertex and the jth vertex and false otherwise.
  // Outputs: all possible colorings of the graph, using at most m colors, so that
  // no two adjacent vertices are the same color. The output for each coloring is
  // an array vcolor indexed from 1 to n, where vcolor[i] is the color
  // (an integer between 1 and m) assigned to the ith vertex.


  bool promising(graph g, int i, int* vcolor);

  template <typename Item>
  Item* get_vector_space(const int n)
  // Prostcondition: Return the array containing n spaces
  {
    Item* v = new Item[n];
    return (v-1); // offset the pointer
  }
}

#endif

 

  • mcoloring.cpp
// File: mcoloring.cpp
#include <iostream>
#include <iomanip> // Provides setw
#include "mcoloring.h"

namespace algorithms
{
  void m_coloring(graph g, int i, int *vcolor)
  {
    const int m = 3; // m is the number of colors.

    if (promising(g, i, vcolor))
    {
      if (i == (g.get_size()))
      {
        // Print vcolor[1] through vcolor[n];
        for (int i = 1; i <= g.get_size(); ++i)
          std::cout << std::setw(4) << g[i] << "'s color: " << vcolor[i];
        std::cout << std::endl;
      }
      else
      {
        for (int color = 1; color <= m; ++color)
        {
          vcolor[i + 1] = color;
          m_coloring(g, i + 1, vcolor);
        }
      }
    }
  }

  bool promising(graph g, int i, int *vcolor)
  {
    int j;
    bool is_switch;
    const int EDGES_CONN = 1;

    j = 1;
    is_switch = true;

    while (j < i && is_switch)
    {
      if (g.get_edge(i, j) == EDGES_CONN && vcolor[i] == vcolor[j])
        is_switch = false;

      ++j;
    }

    return is_switch;
  }
} // namespace algorithms

 

  • mcoloringtest.cpp
// File: mcoloringtest.cpp
#include <cstdlib>
#include <iostream>
#include "mcoloring.h"
#include "graph.h"
using namespace algorithms;

int main( )
{
  const int GRAPH_SIZE = 4;
  const int EDGES_CONN = 1;

  graph W(GRAPH_SIZE);
  int* vcolor = get_vector_space<int>(GRAPH_SIZE);

  W.set_vertex("v1");
  W.set_vertex("v2");
  W.set_vertex("v3");
  W.set_vertex("v4");
  W.set_edge(1, 2, EDGES_CONN);
  W.set_edge(1, 3, EDGES_CONN);
  W.set_edge(1, 4, EDGES_CONN);
  W.set_edge(2, 1, EDGES_CONN);
  W.set_edge(2, 3, EDGES_CONN);
  W.set_edge(3, 1, EDGES_CONN);
  W.set_edge(3, 2, EDGES_CONN);
  W.set_edge(3, 4, EDGES_CONN);
  W.set_edge(4, 1, EDGES_CONN);
  W.set_edge(4, 3, EDGES_CONN);

  m_coloring(W, 0, vcolor);

  delete [ ](vcolor + 1);
  return EXIT_SUCCESS;
}

 

 

Time Complexity Analysis


Worst-Case Time Complexity

$\displaystyle O(n) =  1 + m + m^2 + m^3 + … + m^n = \frac{m^{n+1} - 1}{m-1} \in \Theta(m^n) $

 

For a given m and n, it is possible to create an instance that checks at least an exponentially large number of nodes (in terms of n). As with any backtracking algorithm, even though the worst case is exponential, the algorithm can be efficient for many large instances.

 

๐Ÿ‘‰ ํ•œ ์ •์ ์—์„œ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์ƒ‰(m๊ฐœ)์„ ์‹œ๋„ํ•ด ๋ด์•ผํ•˜๋ฏ€๋กœ ์ฃผ์–ด์ง„ m, n์— ๋Œ€ํ•ด ์ตœ์†Œํ•œ ์ง€์ˆ˜๋งŒํผ ๋งŽ์€ ๋…ธ๋“œ์˜ ์ˆ˜๋ฅผ ์ ๊ฒ€ํ•˜๋Š” ์ƒํƒœ๊ณต๊ฐ„ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ€์ง€์น˜๊ธฐ๋ฅผ ํ†ตํ•ด ์ƒํƒœ๋…ธ๋“œ์˜ ์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํšจ์œจ์€ ๋” ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค.
n-Queens ๋ฐ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ํ•ฉ ๊ตฌํ•˜๊ธฐ ๋ฌธ์ œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์œ ๋งํ•œ ๋…ธ๋“œ์˜ ์ˆ˜๋ฅผ ์ •ํ™•ํžˆ ๊ตฌํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์€ ์‹ค์ œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ˆ˜ํ–‰ ํ›„ ๊ตฌ์ถ•๋œ ์ƒํƒœ๊ณต๊ฐ„ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ ๊ฐฏ์ˆ˜๋ฅผ ์„ธ์–ด ๋ณด๋Š” ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ๋˜ํ•œ ๋ชฌํ…Œ ์นด๋ฅผ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•ด ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ์ถ”์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

'Algorithms > Backtracking' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Backtracking with the 0-1 Knapsack problem(Depth-First Search)(0-1 ๋ฐฐ๋‚ญ ๋ฌธ์ œ-๊นŠ์ด์šฐ์„ ํƒ์ƒ‰)  (2) 2011.12.24
The Sum-of-Subsets Problem(๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ํ•ฉ ๊ตฌํ•˜๊ธฐ)  (2) 2011.12.23
n-Queens Problem(n-ํ€ธ ๋ฌธ์ œ)  (0) 2011.10.03
Backtracking(๋ฐฑํŠธ๋ž˜ํ‚น)  (0) 2011.08.06
'Algorithms/Backtracking' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • Backtracking with the 0-1 Knapsack problem(Depth-First Search)(0-1 ๋ฐฐ๋‚ญ ๋ฌธ์ œ-๊นŠ์ด์šฐ์„ ํƒ์ƒ‰)
  • The Sum-of-Subsets Problem(๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ํ•ฉ ๊ตฌํ•˜๊ธฐ)
  • n-Queens Problem(n-ํ€ธ ๋ฌธ์ œ)
  • Backtracking(๋ฐฑํŠธ๋ž˜ํ‚น)
Zakarum
Zakarum
  • Zakarum
    Zakr. _archives
    Zakarum
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • Zakarum
      • Cogito, ergo sum
      • Algorithms
        • Eff, Anal, and Order
        • Divide-and-Conquer
        • Dynamic Programming
        • The Greedy Approach
        • Backtracking
        • Branch-and-Bound
      • Et Cetera
        • Job-seeking
      • Not Public
        • MBA
        • Finance
        • 2.3. Civil•Commercial Law
        • 2.2. Credit Analysis (Basic..
        • 2.4. Foreign Exchange
        • 2.1. Accounting Principles ..
        • ITSM
        • Theory of NP
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
    • ๋ฐฉ๋ช…๋ก
    • ๊ธ€์“ฐ๊ธฐ
  • ๋งํฌ

  • ๊ณต์ง€์‚ฌํ•ญ

  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    ์†Œํ”„ํŠธ์›จ์–ด๊ณตํ•™
    ์ผ๋ณธ์—ฌํ–‰
    ๊ธˆ์œตIT ์ฑ„์šฉ์ •๋ณด
    ๋ฏธ๊ตญ์—ฌํ–‰
    ๋Œ€๋งŒ์—ฌํ–‰
    p-np problem
    ์žฌ๋ฌดํšŒ๊ณ„
    ๋ฏผ์ƒ๋ฒ•๊ธฐ์ดˆ3
    ์™ธ๊ตญํ™˜
    0-1 ๋ฐฐ๋‚ญ ๋ฌธ์ œ
    ํšŒ๊ณ„์›๋ฆฌ๊ธฐ์ดˆ1
    ๋ฏผ์ƒ๋ฒ•๊ธฐ์ดˆ1
    ํšŒ๊ณ„์›๋ฆฌ๊ธฐ์ดˆ2
    ๋„คํŠธ์›Œํฌ
    ๋ฐฑํŠธ๋ž˜ํ‚น
    os concept
    ์ดํƒˆ๋ฆฌ์•„์—ฌํ–‰
    process management
    ITIL
    ํƒ์š• ์•Œ๊ณ ๋ฆฌ์ฆ˜
    process scheduling
    ์ตœ์†Œ์‹ ์žฅํŠธ๋ฆฌ
    ์•Œ๊ณ ๋ฆฌ์ฆ˜
    ๋ถ„ํ• ์ •๋ณต๋ฒ•
    ๋ฒ ํŠธ๋‚จ์—ฌํ–‰
    ๋ถ„๊ธฐํ•œ์ •๋ฒ•
    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ
    SNU MBA
    ๋™์ ๊ณ„ํš๋ฒ•
    ์‹ ์šฉ๋ถ„์„๊ธฐ์ดˆ
  • ์ตœ๊ทผ ๋Œ“๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.5
Zakarum
Graph Coloring(๊ทธ๋ž˜ํ”„ ์ฑ„์ƒ‰)
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”