Grade 11 · BacktrackingCitește în română
Map coloring
Original: Colorarea hărților
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)
- Chapter
- Backtracking
Examples
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.
/*
* 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.