Təpə -dən dərinliyə doğru axtarış başladırıq. Təpə -yə daxil olarkən color[v] rəngini alırıq və used[color[v]] dəyərini artırırıq. used[color[v]] dəyəri, təpəsindən təpəsinə qədər (daxil olmaqla) yol boyunca color[v] rənginin neçə dəfə təkrarladığını bildirir. Əgər bu rəng bu yolda yalnız bir dəfə təkrarlanırsa, o zaman təpəsi yaxşıdır və biz onu nəticə dəstinə əlavə edirik.
Təpə -dən çıxərkən used[color[v]] dəyərini azaldırıq.
Misal
Birinci misaldakı qraf bu cür görünür:
Təpə yaxşı deyil, çünki 1 - 2 - 5 yolunda təpələr və eyni rəngdədir.
Təpə yaxşıdır, çünki 1 - 2 - 3 - 6 yolunda aralıq təpələrin rəngləri təpəsinin rəngindən fərqlidir.
Alqoritmanın tətbiqi
Daxil olan qrafı qonşuluq siyahısında saxlayırıq. İşlədici massivlər elan edirik.
vector<int> used, color;
vector<vector<int>> g;
set<int> st;dfs funksiyası dərinliyə doğru axtarışı həyata keçirir. dəyişəni təpəsinin əcdadıdır.
void dfs(int v, int par)
{Təpə rəngi color[v]-dir. təpəsindən bu rəngdə təpənin qarşılandığını qeyd edirik.
used[color[v]]++;used[color[v]] dəyəri, təpəsindən təpəsinə qədər yolda (daxil olmaqla) color[v] rənginin neçə dəfə qarşılandığını göstərir. Əgər bu rəng yolda yalnız bir dəfə qarşılanırsa, təpəsi yaxşı hesab olunur və onu nəticə dəsti -ə əlavə edirik.
if (used[color[v]] == 1) st.insert(v);Təpə -dən çıxan bütün qövs (v, to)-ları gözdən keçirik. Əgər to təpəsi -nin əcdadı deyil (to \ne par), ondan dərinliyə doğru axtarış başladırıq. Bu zaman təpəsinin əcdadı olur.
for (int to : g[v])
if (to != par) dfs(to, v);Təpə -dən çıxanda used[color[v]] dəyərini azaldırıq.
used[color[v]]--;
}Proqramın əsas hissəsi. Təpələrin sayı və rəng massivi oxunur.
scanf("%d", &n);
color.resize(n + 1);
for (i = 1; i <= n; i++)
scanf("%d", &color[i]);Qraf oxunur.
used.resize(100001);
g.resize(n + 1);
for (i = 1; i < n; i++)
{
scanf("%d %d", &x, &y);
g[x].push_back(y);
g[y].push_back(x);
}Təpə -dən dərinliyə doğru axtarış başlayırıq.
dfs(1, 1);Yaxşı təpələr çıxış edilir. Onlar dəstində saxlanır.
for (int val : st)
printf("%d\n", val);