Dərinlik üzrə keçməyi təpəsindən başlayaraq icra edək. Hər bir təpə üçün iki dəyəri hesablayacağıq:
— təpə -dən təpə -ə qədər məsafə. Əgər — təpəsinin valideyni isə, onda
— təpə -dən -də köklü alt ağacın ən yaxın yarpağına qədər məsafə. Əgər to_1, to_2, ..., to_k — təpəsinin övladlarıdırsa, onda
Əgər ağacın yarpağıdırsa, onda h[v] = 0 qoyaq.
Daha sonra ikinci dərinlik üzrə keçməyi başladaq. Bu keçmə zamanı dəyərini hesablayacağıq — təpəsində köklü alt ağacda bəzi yarpaqlarda yerləşdirilməli olan minimum dost sayını, belə ki, kəpənəyi mütləq tutmaq olar, əgər o, bu alt ağacı seçərsə.
Əgər h[v] \le d[v]-dirsə, onda res[v] = 1. Bu halda, təpəsinin alt ağacında minimum dərinliyi olan yarpağa bir dostu yerləşdirmək kifayətdir: o, ağacın kökündən çıxaraq keçmədən əvvəl təpəsinə çatacaq.
Əks halda, əgər to_1, to_2, ..., to_k — təpəsinin övladlarıdırsa, onda
Əgər kəpənək təpəsinin özündə tutulmazsa, -dən çıxan alt ağaclardakı hər hansı birindən onu tutmaq üçün hazır olmalıdırlar.
Tələb olunan cavab dəyəridir.
Nümunə
Birinci nümunədə (şəkilin sol tərəfində) iki dost lazımdır, onların iki çıxışda yerləşdirilməli olduğu yerdə. Kəpənək ya təpə -dən təpə -yə və ya təpə -ə uça bilər. Hər hansı bir halda, onu alınacaq.
İkinci nümunədə (şəkilin sağ tərəfində) bir dost kifayətdir, onu iki çıxışdan birinə — təpə və ya -ə yerləşdirmək olar. Bir dəqiqə ərzində kəpənək təpə -dən təpə -yə çatacaq. Eyni zamanda dostu təpə -yə çatacaq və onu orada tutacaq.
Növbəti nümunəyə baxaq. Kəpənəyi tutmaq üçün üç dost lazımdır.
Alqoritmin icrası
Sonsuzluq və işçi massivləri elan edək.
#define INF 2000000000
vector<vector<int> > g;
vector<int> d, h, res;dfs funksiyası (v, p, cnt) dərinlik üzrə keçməni təpəsindən başlayır və dəyərini qaytarır. Burada — təpəsinin əcdadı, və — təpəsindən -ə qədər olan məsafədir. Keçmə prosesi zamanı hər bir təpəsi üçün və dəyərləri hesablanır.
int dfs(int v, int p = -1, int cnt = 0)
{dəyəri, təpəsindən -ə olan məsafə, -də saxlanılır.
d[v] = cnt;
int height = INF;təpəsinin bütün övladlarını nəzərdən keçiririk. v \to to olan qövsü nəzərdən keçiririk. Əgər -in əcdadı ilə eynidirsə (to = p), növbəti övlada keçirik.
for (int to : g[v])
if (to != p) dəyişənində aşağıdakı dəyəri hesablayırıq
burada to_1, to_2, ..., to_k — təpəsinin övladlarıdır.
Əgər height = INF, bu təpəsinin yarpaq olduğunu və h[v] = 0-ı təyin etməyin lazım olduğunu bildirir. Əks halda,
funksiya geriyə qaytarır
return h[v] = (height == INF) ? 0 : 1 + height;
}dfs2 funksiyası dərinlik üzrə keçməni təpəsindən başlayır və -i qaytarır. Burada — təpəsinin əcdadıdır.
int dfs2(int v, int p = -1)
{
int s = 0;Qoy to_1, to_2, ..., to_k — təpəsinin övladlarıdır. dəyişənində aşağıdakı cəmi hesablayacağıq:
for (int to : g[v])
if (to != p)
{
dfs2(to, v);
s += res[to];
}Əgər h[v] \le d[v]-dirsə, bir dost kifayətdir, və res[v] = 1. Əks halda
return res[v] = (h[v] <= d[v]) ? 1 : s;
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq. Qrafik 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);
}Massivləri başladırıq.
d.resize(n + 1);
h.resize(n + 1);
res.resize(n + 1);İki dərinlik üzrə keçmə işə salırıq. Birinci keçmə hər bir təpəsi üçün və dəyərlərini hesablayır.
dfs(1);
dfs2(1);Cavabı çıxırıq — kəpənəyi tutmaq üçün lazım olan minimum dost sayını.
printf("%lld\n", res[1]);