Ağacda Məsafə I#11430

Ağacda Məsafə I (Həll təhlili)

Ağacın diametrini iki dəfə dərinlik birinci axtarışı (DFS) ilə tapın.

Çünki ağac əlaqəli bir dövrsüz qrafdir, həm dərinlik birinci axtarışı (DFS), həm də eninə birinci axtarışı (BFS) başlanğıc vertex-dən digər bütün vertexlərə ən qısa məsafələri düzgün tapır.

və iki zirvə olsun ki, aralarındakı məsafə maksimum olsun — yəni ağacın diametrini təşkil edən zirvələr.

Vertex -dan digər bütün zirvələrə ən qısa məsafələri hesablayaq və onları massivinə, vertex -dən isə massivinə qeyd edək.

Beləliklə, hər bir zirvə üçün uzaq gələcək zirvəyə qədər olan ən böyük məsafə belə olur

max(dista[i], distb[i])

Misal

Misal üçün verilmiş ağacı nəzərdən keçirək.

Ağacın diametri məsələn, və zirvələri arasında ola bilər.

Alqoritmin həyata keçirilməsi

Girişdəki ağac qonşuluq listi şəklində verilir.

və zirvələrindən olan ən qısa məsafələr və massivlərində saxlanılır.

vector<vector<int>> g;
vector<int> dista, distb;

dfs funksiyası vertex -dən dərinlik birinci axtarışı həyata keçirir.

void dfs(int v, int d, vector<int>& dist, int p = -1)
{

dist[v]-də mənbədən vertexinə qədər olan ən qısa məsafəni qeyd edirik.

  dist[v] = d;

Bütün kənarları (v, to) araşdırırıq. vertexinin oğlu olan hər bir vertexi üçün (vertex vertex -nin atası deyil) dərinlik birinci axtarışı həyata keçiririk.

  for (int to : g[v])
    if (to != p) dfs(to, d + 1, dist, v);
}

Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.

scanf("%d", &n);
g.resize(n + 1);
dista.resize(n + 1);
distb.resize(n + 1);

Qeyri-istiqatlı ağac yaradırıq.

for (i = 1; i < n; i++)
{
  scanf("%d %d", &u, &v);
  g[u].push_back(v);
  g[v].push_back(u);
}

zirvəsindən olan ən qısa məsafələri tapırıq. Ondan ən uzaq olan zirvə zirvəsidir.

dfs(1, 0, dista, -1);
a = max_element(dista.begin() + 1, dista.begin() + n + 1) - dista.begin();

Sonra zirvəsindən olan ən qısa məsafələri hesablayaq və onları massivində saxlayırıq. -dan ən uzaq olan zirvə zirvəsidir. və zirvələri arasındakı məsafə ağacın diametridir.

dfs(a, 0, dista, -1);
b = max_element(dista.begin() + 1, dista.begin() + n + 1) - dista.begin();

zirvəsindən olan ən qısa məsafələri hesablayaq və onları massivində saxlayırıq.

dfs(b, 0, distb, -1);

Hər bir zirvə üçün ən uzaq zirvəyə qədər olan məsafəni çap edirik.

for (i = 1; i <= n; i++)
  printf("%d ", max(dista[i], distb[i]));
printf("\n");

Python tətbiqi

Rekursiya üçün steki artırın.

import sys
sys.setrecursionlimit(1000000)

dfs funksiyası vertex -dən dərinlik birinci axtarışı həyata keçirir.

def dfs(v, d, dist, p =- 1):

dist[v]-də mənbədən vertexinə qədər olan ən qısa məsafəni qeyd edirik.

  dist[v] = d

Bütün kənarları (v, to) araşdırırıq. vertexinin oğlu olan hər bir vertexi üçün (vertex vertex -nin atası deyil) dərinlik birinci axtarışı həyata keçiririk.

  for to in g[v]:
    if to != p:
      dfs(to, d + 1, dist, v)

Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.

n = int(input())
g = [[] for _ in range(n + 1)]
dista = [0] * (n + 1)
distb = [0] * (n + 1)

Qeyri-istiqatlı ağac yaradırıq.

for _ in range(n - 1):
  u, v = map(int, input().split())
  g[u].append(v)
  g[v].append(u)

zirvəsindən olan ən qısa məsafələri tapırıq. Ondan ən uzaq olan zirvə zirvəsidir.

dfs(1, 0, dista)
a = dista.index(max(dista[1:]))

Sonra zirvəsindən olan ən qısa məsafələri hesablayaq və onları massivində saxlayırıq. -dan ən uzaq olan zirvə zirvəsidir. və zirvələri arasındakı məsafə ağacın diametridir.

dfs(a, 0, dista)
b = dista.index(max(dista[1:]))

zirvəsindən olan ən qısa məsafələri hesablayaq və onları massivində saxlayırıq.

dfs(b, 0, distb)

Hər bir zirvə üçün ən uzaq zirvəyə qədər olan məsafəni çap edirik.

result = [max(dista[i], distb[i]) for i in range(1, n + 1)]
print(*result)