İki rəngli olma#3165

İki rəngli olma (Həll təhlili)

Məsələdə qrafı elə rəngə boyamağın mümkün olub-olmadığını yoxlamaq lazımdır ki, hər hansı iki qonşu təpə fərqli rəngdə olsun. Belə qraf ikitərəfli (двудольный) adlanır.

Əgər qraf üzərində dərinliyinə axtarış həyata keçirsək, onda:

Yəni təpələrin rəngləri gəzintinin dərinliyi üzrə növbələşməlidir.

Məsələnin həlli üçün dərinliyinə axtarışdan istifadə edəcəyik. Əvvəlcə bütün təpələr ziyarət edilməmiş sayılır və rəngi ilə işarələnir. Qrafı gəzərkən təpələri iki rəngə: və -yə boyayacağıq. Əgər cari təpənin rəngi -dirsə (burada i = 1 və ya ), onda dərinliyinə gəzinti zamanı keçdiyimiz hər növbəti təpəni 3 - i rənginə boyayırıq. Bu zaman hər addımda yoxlayırıq ki, heç bir iki qonşu təpə eyni rəngə boyanmasın.

Misal

Misalda verilmiş qraflar aşağıdakı görünüşə malikdir:

Alqoritmin realizasiyası

Qrafın qonşuluq matrisini MAX = 1001 ölçülü massivində saxlayacağıq (təpələrin nömrələnməsi -dən n \le 1000-ə qədər aparılır). massivi hər təpənin rəngi haqqında məlumatı saxlayır. qlobal dəyişəni boyamanın düzgünlüyünə cavabdehdir: eyni rəngə boyanmış iki qonşu təpə aşkar edildiyi anda bu dəyişən qiymətini alır.

#define MAX 1000
int g[MAX][MAX], used[MAX], flag;

dfs funksiyası dərinliyinə axtarışı yerinə yetirir. Ona iki parametr ötürülür: cari təpə və onun rəngi .

void dfs(int v, int color = 1)
{

Əgər əvvəllər artıq tələb olunan boyamanın mümkün olmadığı hal aşkar edilibsə (flag = 1), funksiyanın icrası dayandırılır.

  if (flag) return;

təpəsini color rənginə boyayırıq.

  used[v] = color;

təpəsindən keçə biləcəyimiz bütün təpələrinə baxırıq, dərinliyinə gəzintini davam etdirərək.

  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;
}

Proqramın əsas dövrü. Qrafın təpələrinin sayı və tillərinin sayı -i oxuyuruq. Qonşuluq matrisini və massivini sıfırlayırıq.

while(scanf("%d %d",&n,&l), n)
{
   memset(g,0,sizeof(g));
   memset(used,0,sizeof(used));

Qrafın tillərini oxuyuruq.

   for(i = 0; i < l; i++)
   {
     scanf("%d %d",&a,&b);
     g[a][b] = g[b][a] = 1;
   }

dəyişənini sıfırlayırıq və dərinliyinə axtarışı birinci təpədən başlayaraq işə salırıq, əvvəlcədən ona rəngini mənimsətdikdən sonra.

   flag = 0; 
   dfs(1);

dəyişəninin qiymətindən asılı olaraq nəticəni çap edirik.

   if (flag) printf("NOT BICOLOURABLE.\n");
   else printf("BICOLOURABLE.\n");
}