Bütün fermaları yoluxdurmaq üçün iki növ əməliyyat yerinə yetirmək lazımdır:
Hərəkətlər. Hər bir yolun ən azı bir dəfə istifadə edilməsi ilə n - 1 inək göndərilməlidir. Deməli, yalnız fermalar arasında inəkləri hərəkət etdirmək üçün minimum n - 1 gün tələb olunacaq.
İki qatlama. Fermada əvvəlcə yalnız bir xəstə inək olduğu üçün əvvəlcə iki qatlama əməliyyatları edərək lazım olan sayda inək yetişdirməliyik.
Qeyd edək ki, iki qatlamalar və keçidlər yoluxmadan sonra ağacın fərqli yerlərində baş verə bilər.
Tutaq ki, fermasına bir xəstə inək gəlib. Əgər ferması ağacda uşaqa sahibdirsə, o, qonşuya xəstə inəklər göndərməlidir, buna görə inək olmalıdır.
Əvvəlcə fermasında inək olur. İki qatlamaları edirik: 1 \to 2 \to 4 \to 8 ... . inək əldə etmək üçün minimal iki qatlama sayı ⌈log_2 x⌉-dir.
Beləliklə, xəstəliyi bütün fermalara yaymaq üçün lazım olan minimal günlər sayı:
Təcrübədə, məsələnin şərtinə görə hər bir fermada hər hansı bir zamanda ən azı bir xəstə inək olmalıdır. Şərtə görə, bütün fermaları yoluxdurduqdan sonra hər fermada ən azı bir xəstə inək qalması lazım deyil.
Alqoritmin Tətbiqi
Ağacı qonşuluq siyahısı şəklində saxlayırıq.
vector<vector<int>> g;dfs funksiyası düyünündən başlayaraq dərindən keçmə edərək bu düyündə köklü alt-ağacda yoluxmuş inəkləri iki qatlamaq üçün lazım olan günlərin sayını qaytarır. düyününün atası -dır.
int dfs(int v, int par = 0)
{
int ans = 0;
for (int to : g[v])
if (to != par)
ans += dfs(to, v);
return ans + ceill(log2(g[v].size()));
}Proqramın əsas hissəsi. Daxil olan məlumatları oxuyuruq. Qrafı qururuq.
scanf("%d", &n);
g.resize(n + 1);
for (i = 0; i < n - 1; i++)
{
scanf("%d %d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}Düyün -dən dərindən keçmə axtarışını işə salırıq və bütün fermaları yoluxdurmaq üçün lazım olan minimal günlərin sayını hesablayırıq. Cavabı dəyişənində saxlayırıq.
res = dfs(1) + n - 1;Cavabı çıxarırıq.
printf("%d\n", res);