Yeganə topoloji sıralama#10652

Yeganə topoloji sıralama (Həll təhlili)

Biz Kahn alqoritmindən istifadə edirik. Yadda saxlayaq ki, o, giriş dərəcəsi sıfır olan təpələrin növbəsini saxlayır – bunlar məhz topoloji sıralamanın növbəti mövqeyinə yerləşdirilə bilən təpələrdir. Hər iterasiyada növbədən bir təpə çıxarılır və cavaba əlavə edilir, onun bütün qonşularının giriş dərəcəsi azaldılır. Giriş dərəcəsi sıfır olan təpələr növbəyə əlavə edilir.

Əsas müşahidə: topoloji sıralama o zaman və yalnız o zaman unikaldır ki, hər çıxarılmadan əvvəl növbədə dəqiq bir təpə olsun.

Mürəkkəblik. Hər təpə və hər tərəf bir dəfə emal olunur, buna görə işləmə vaxtı O(n + m)-dir.

Nümunə

Test hallarından olan qraflar aşağıdakı kimidir:

Birinci nümunədə topoloji sıralama unikaldır:

İkinci nümunədə isə iki mümkün topoloji sıralama var:

Alqoritmin həyata keçirilməsi

Giriş qrafını qonşuluq siyahısı şəklində saxlayırıq. Təpələrin giriş dərəcələri InDegree massivində saxlanılır. növbəsini elan edirik.

vector\u003cvector\u003cint\u003e \u003e g;
vector\u003cint\u003e InDegree;
deque\u003cint\u003e q;

Giriş qrafını oxuyuruq. Hər tərəfi üçün InDegree[b]-ni artırırıq.

scanf("%d %d", &n, &m);
g.resize(n + 1);
InDegree.resize(n + 1);
for (i = 0; i < m; i++)
{
  scanf("%d %d", &a, &b);
  g[a].push_back(b);
  InDegree[b]++;
}

Giriş dərəcəsi sıfır olan bütün təpələri növbəsinə əlavə edirik.

for (i = 1; i < InDegree.size(); i++)
  if (!InDegree[i]) q.push_back(i);

Topoloji sıralama unikal olarsa, flag = 1 təyin edirik.

flag = 1;

növbəsi boş olmadığı müddətcə alqoritmi davam etdiririk.

while (!q.empty())
{

Əgər növbədə birdən çox təpə varsa, onda topoloji sıralama unikal deyil.

  if (q.size() > 1) flag = 0;

Növbədən cari təpəsini çıxarırıq.

  v = q.front(); q.pop_front();

(v, to) tərəflərini qrafdan silirik. Hər belə tərəf üçün təpəsinin giriş dərəcəsini azaldırıq. Əgər təpəsinin giriş dərəcəsi sıfır olarsa, onu növbəyə əlavə edirik.

  for (int to : g[v])
  {
    InDegree[to]--;
    if (!InDegree[to]) q.push_back(to);
  }
}

dəyərindən asılı olaraq cavabı çap edirik.

if (flag == 1)
  printf("YES\n");
else
  printf("NO\n");