Metro sxemi təpədən və tilindən ibarət əlaqəli istiqamətləndirilməmiş qrafdır. təpəsi olan və məhz n - 1 tilə malik əlaqəli qraf ağacdır. Ağaca daha bir til əlavə etmək məhz bir dövr yaradır. Buna görə də şərtdəki qraf yeganə dövrdən (halqavari xətdən) ibarətdir ki, onun təpələrindən ağaclar (bəlkə də boş) asılmışdır.
Hər bir təpə üçün dövrün ən yaxın təpəsinə qədər olan ən qısa yolun uzunluğunu tapmaq lazımdır. Dövr təpələri üçün cavab -a bərabərdir. Məsələ iki mərhələdə həll olunur.
1-ci mərhələ. Dövrün ayrılması: yarpaqların ardıcıl silinməsi
Bütün təpələrin dərəcələrini hesablayaq. Dərəcəsi olan bütün təpələri, yəni yarpaqları, növbəyə yerləşdirək. Növbə boş olmayana qədər, ondan təpəsini çıxarırıq və onu silinmiş kimi qeyd edirik. Sonra onun hələ silinməmiş hər bir qonşusunun dərəcəsini azaldırıq. Əgər qonşunun dərəcəsi -ə bərabər olarsa, deməli o özü yarpağa çevrilib və biz onu növbəyə əlavə edirik.
Proses tamamlandıqdan sonra yalnız dövrün təpələri silinməmiş qalacaq. Bu, iki müşahidədən irəli gəlir:
Dövrün təpəsi heç vaxt yarpağa çevrilməyəcək. Onun həmişə dövr üzrə iki qonşusu var, onlar da silinmir. Bu, prosesin addımları üzrə induksiya ilə ciddi şəkildə sübut olunur.
Asılı ağacın hər bir təpəsi silinəcək. Yarpaqların silinməsi ağacı aşağıdan yuxarıya, yarpaqlardan dövrə bağlanma nöqtəsinə qədər "gəmirir". Bu prosedur Kan alqoritminə əsasən aparılan topoloji sıralamaya analojidir, sadəcə istiqamətləndirilməmiş qrafa tətbiq edilib.
2-ci mərhələ. Çoxmənbəli enlik üzrə axtarış
Bütün dövr təpələri üçün d[v] = 0 qəbul edək, qalanları üçün isə d[v] = –1 (ziyarət edilməyib). Bütün dövr təpələrini eyni zamanda növbəyə yerləşdirək və onlardan enlik üzrə axtarışı başladaq. təpəsi növbədən çıxarıldıqda, onun hər bir ziyarət edilməmiş qonşusu d[w] = d[u] + 1 qiymətini alır və növbəyə əlavə olunur.
Çoxmənbəli enlik üzrə axtarış təpələri həmin çoxluğa qədər olan məsafənin qeyri-azalan sırası ilə emal edir. Buna görə də -dən halqavari xəttə qədər minimal keçid sayına bərabərdir. Dövrdən kənarda olan hər şey ağac olduğu üçün, hər stansiyadan halqaya qədər olan yol əslində yeganədir.
Qrafda dərəcəsi olan təpələr olduqca, onları siləcəyik.
Belə təpələr qalmadıqda, qrafda yalnız dövr yaradan təpələr qalacaq.
Bu proses tərs topoloji sıralamanı xatırladır: biz yalnız "daxili" təpələr qalana qədər yarpaqları ardıcıl olaraq siririk — məhz onlar da dövrü təşkil edir.
Bundan sonra dövrə daxil olan bütün təpələrdən eyni zamanda enlik üzrə axtarışı işə salırıq. Beləliklə, qalan hər bir təpə üçün halqanın ən yaxın təpəsinə qədər minimal addım (keçid) sayı müəyyən edilir.
Misal
Birinci misalda bütün təpələr bir dövrə daxildir, buna görə də hər biri üçün məsafə -a bərabərdir.
İkinci misalda dövrü və təpələri yaradır, qalan təpələr isə ondan müəyyən məsafədədir.
Alqoritmin reallaşdırılması
Qrafın qonşuluq siyahısını , həmçinin köməkçi massivləri elan edək:
— təpənin silinmə əlaməti: əgər təpəsi yarpaq kimi artıq silinibsə used[v] = 1, əgər o hələ qrafda qalırsa used[v] = 0. Birinci mərhələ tamamlandıqdan sonra sıfır qiymətlər yalnız dövr təpələrində saxlanılacaq;
— məsafələr massivi: dist[v] təpəsindən dövrün ən yaxın təpəsinə qədər keçid sayına bərabərdir ( qiyməti təpənin hələ ziyarət edilmədiyini bildirir);
— təpələrin cari dərəcələri: deg[v] təpəsinin hələ silinməmiş qonşularının sayına bərabərdir.
növbəsi alqoritmin hər iki mərhələsində istifadə olunur: əvvəlcə yarpaqların ardıcıl silinməsi üçün, sonra isə çoxmənbəli enlik üzrə axtarış üçün.
vector\u003cvector\u003cint\u003e \u003e g;
vector\u003cint\u003e used, dist, deg;
queue\u003cint\u003e q;Giriş məlumatlarını oxuyuruq. Qrafı qururuq.
scanf("%d", \u0026n);
g.resize(n + 1);
for (i = 0; i \u003c n; i++)
{
scanf("%d %d", \u0026a, \u0026b);
g[a].push_back(b);
g[b].push_back(a);
}Təpələrin ilkin dərəcələrini hesablayırıq: təpəsinin dərəcəsi onun qonşuluq siyahısının ölçüsünə bərabərdir. Bütün yarpaqları, yəni dərəcəsi olan təpələri, növbəsinə yerləşdiririk və dərhal silinmiş kimi qeyd edirik (used[i] = 1).
used.resize(n + 1, 0);
deg.resize(n + 1, 0);
for (i = 1; i \u003c= n; i++)
{
deg[i] = g[i].size();
if (deg[i] == 1)
{
q.push(i);
used[i] = 1;
}
}Yarpaqları ardıcıl olaraq siririk. Zahirən bu dövr enlik üzrə axtarışa oxşayır, lakin təpə ilk dəfə aşkarlananda deyil, yalnız özü yarpağa çevriləndə növbəyə düşür. Növbədən təpəsini çıxarırıq və onun qonşularını araşdırırıq. Artıq silinmiş kimi qeyd edilmiş qonşuları buraxırıq. Hər bir silinməmiş qonşu üçün dərəcəni azaldırıq, çünki (v, to) tili təpəsi ilə birlikdə qrafdan yox olur.
while (!q.empty())
{
int v = q.front(); q.pop();
for (int to : g[v])
if (used[to] == 0)
{
deg[to]--;Əgər azaldıqdan sonra to təpəsinin dərəcəsi -ə bərabər olarsa, deməli onun yalnız bir silinməmiş qonşusu qalıb, yəni o özü yarpağa çevrilib. Onu növbəyə yerləşdiririk və silinmiş kimi qeyd edirik. Dövr təpələri heç vaxt dərəcəsinə çatmır, buna görə də proses halqavari xətdə dayanır.
if (deg[to] == 1)
{
q.push(to);
used[to] = 1;
}
}
}Bu anda used[i] = 0 bərabərliyi yalnız o halda doğrudur ki, təpəsi dövrə aiddir.
massivini qiyməti ilə ilkinləşdiririk (bütün təpələr ziyarət edilməyib). Növbə bu anda artıq boşdur, lakin boş növbənin təyin edilməsi ikinci dolanmadan əvvəl onu açıq şəkildə sıfırlayır. Sonra dövrün hər bir təpəsini növbəyə yerləşdiririk və onun üçün dist[i] = 0 qəbul edirik — halqavari xəttin bütün təpələri eyni zamanda enlik üzrə axtarışın mənbələrinə çevrilir.
dist = vector\u003cint\u003e(n + 1, -1);
q = queue\u003cint\u003e();
for (i = 1; i \u003c= n; i++)
if (used[i] == 0)
{
q.push(i);
dist[i] = 0;
}Çoxmənbəli enlik üzrə axtarışı işə salırıq. Növbədən təpəsini çıxarırıq. Onun hər bir ziyarət edilməmiş to~(dist[to] = –1) qonşusu dist[v] + 1 məsafəsini alır və növbəyə əlavə olunur. Dövr təpələri əvvəldən məsafəsi ilə qeyd edilib, buna görə dolanma halqaya qayıtmır və yalnız asılı ağacların dərinliyinə doğru yayılır. Təpələr növbədən məsafənin qeyri-azalan sırası ilə çıxarıldığı üçün, hər bir dist[to] qiyməti ən qısadır.
while (!q.empty())
{
int v = q.front(); q.pop();
for (int to : g[v])
if (dist[to] == -1)
{
q.push(to);
dist[to] = dist[v] + 1;
}
}Stansiyalardan halqavari xəttə qədər olan məsafələri onların nömrələri sırası ilə çap edirik.
for (i = 1; i \u003c= n; i++)
printf("%d ", dist[i]);
printf("\n");