Nel problema occorre verificare se sia possibile colorare il grafo con colori in modo che due vertici adiacenti qualsiasi abbiano colori diversi. Un tale grafo si chiama bipartito.
Se si effettua una ricerca in profondità sul grafo, allora:
Sia il primo vertice di colore ;
Allora tutti i suoi vicini devono avere colore ;
I vicini dei vertici di colore devono nuovamente avere colore ;
E così via...
Ossia i colori dei vertici devono alternarsi in base alla profondità dell'attraversamento.
Per risolvere il problema utilizzeremo la ricerca in profondità. Inizialmente tutti i vertici sono considerati non visitati e contrassegnati con il colore . Nel processo di attraversamento del grafo coloreremo i vertici con due colori: e . Se il vertice corrente ha colore (dove i = 1 oppure ), allora ogni vertice successivo in cui ci spostiamo durante l'attraversamento in profondità viene colorato con il colore 3 - i. Allo stesso tempo, a ogni passo verifichiamo che due vertici adiacenti qualsiasi non siano colorati con lo stesso colore.
Esempio
I grafi presentati nell'esempio hanno il seguente aspetto:
Implementazione dell'algoritmo
La matrice di adiacenza del grafo verrà memorizzata in un array di dimensione MAX = 1001 (la numerazione dei vertici va da a n \le 1000). L'array contiene le informazioni sul colore di ciascun vertice. La variabile globale è responsabile della correttezza della colorazione: non appena vengono individuati due vertici adiacenti colorati con lo stesso colore, questa variabile assume il valore .
#define MAX 1000
int g[MAX][MAX], used[MAX], flag;La funzione dfs esegue la ricerca in profondità. Le vengono passati due parametri: il vertice corrente e il suo colore .
void dfs(int v, int color = 1)
{Se in precedenza era già stato rilevato un caso in cui la colorazione richiesta è impossibile (flag = 1), l'esecuzione della funzione viene interrotta.
if (flag) return;Contrassegniamo il vertice con il colore color.
used[v] = color;Esaminiamo tutti i vertici in cui è possibile spostarsi dal vertice , continuando l'attraversamento in profondità.
Se il vertice non è ancora stato visitato, avviamo da esso la ricerca in profondità, passando alla funzione dfs il colore opposto.
Se il vertice è già stato visitato, verifichiamo la correttezza della colorazione: se i vertici e hanno lo stesso colore, ciò significa una violazione della condizione di bipartizione, e impostiamo flag = 1.
for (int i = 1; i \le n; i++)
if (g[v][i] == 1)
if (used[i] == 0) dfs(i, 3 - color); else
if (used[v] == used[i]) flag = 1;
}Ciclo principale del programma. Leggiamo il numero di vertici e il numero di lati del grafo. Azzeriamo la matrice di adiacenza e l'array .
while(scanf("%d %d",&n,&l), n)
{
memset(g,0,sizeof(g));
memset(used,0,sizeof(used));Leggiamo i lati del grafo.
for(i = 0; i < l; i++)
{
scanf("%d %d",&a,&b);
g[a][b] = g[b][a] = 1;
}Azzeriamo la variabile , e avviamo la ricerca in profondità, iniziando dal primo vertice, dopo avergli assegnato preliminarmente il colore .
flag = 0;
dfs(1);In base al valore della variabile stampiamo il risultato.
if (flag) printf("NOT BICOLOURABLE.\n");
else printf("BICOLOURABLE.\n");
}