Grade 11 · BacktrackingCitește în română

Map coloring

Original: Colorarea hărților

ExponentialC++1782 lines1 example

The idea

A map has n countries numbered from 1, and m pairs (a, b) say that countries a and b are neighbours. We color every country with one of the colors 1..4 so that two neighbouring countries have different colors. x[k] is the color of country k; it is valid if it differs from the colors of the neighbours already colored (those with a smaller index). The first coloring found (the lexicographically smallest) is printed.

Original description (Romanian)

O hartă are n țări numerotate de la 1, iar m perechi (a, b) spun că țările a și b sunt vecine. Colorăm fiecare țară cu una dintre culorile 1..4 astfel încât două țări vecine să aibă culori diferite. x[k] este culoarea țării k; ea e validă dacă diferă de culorile vecinilor deja colorați (cei cu indice mai mic). Se afișează prima colorare găsită (cea mai mică lexicografic).

Complexity
O(4^n · n) in the worst case, usually much less
Grade
Grade 11 (Clasa a XI-a)

Examples

Example 1

Input

5 7
1 2
1 3
2 3
2 4
3 4
4 5
3 5

Expected output

1 2 3 1 2

The code

Comments are in Romanian, as in the original collection. Edit freely: you can reset at any time.

colorarea-hartilor.cpp
/*
 * Titlu: Colorarea hărților
 * Clasa: 11
 * Capitol: Metoda backtracking
 * Descriere: O hartă are n țări numerotate de la 1, iar m perechi (a, b) spun că țările
 *            a și b sunt vecine. Colorăm fiecare țară cu una dintre culorile 1..4 astfel
 *            încât două țări vecine să aibă culori diferite. x[k] este culoarea țării k;
 *            ea e validă dacă diferă de culorile vecinilor deja colorați (cei cu indice
 *            mai mic). Se afișează prima colorare găsită (cea mai mică lexicografic).
 * Complexitate: O(4^n · n) în cel mai rău caz, de obicei mult mai puțin
 *
 * Exemplu
 * Intrare:
 * 5 7
 * 1 2
 * 1 3
 * 2 3
 * 2 4
 * 3 4
 * 4 5
 * 3 5
 * Ieșire: 1 2 3 1 2
 */
#include <iostream>
using namespace std;

int n, m, x[50];
bool vecin[50][50], gasit = false;

bool valid(int k)
{
    for (int i = 1; i < k; i++)
    {
        if (vecin[i][k] && x[i] == x[k])
        {
            return false;
        }
    }
    return true;
}

void back(int k)
{
    for (int c = 1; c <= 4 && !gasit; c++)
    {
        x[k] = c;
        if (valid(k))
        {
            if (k == n)
            {
                gasit = true;
                for (int i = 1; i <= n; i++)
                {
                    cout << x[i] << ' ';
                }
                cout << '\n';
            }
            else
            {
                back(k + 1);
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        cin >> a >> b;
        vecin[a][b] = vecin[b][a] = true;
    }
    back(1);
    if (!gasit)
    {
        cout << "Nu exista colorare cu 4 culori\n";
    }
    return 0;
}

Runs on a real g++ (C++17, -O2) through Compiler Explorer. Keep runs short; there's a time limit.