Unikal rəng#10654

Unikal rəng (Həll təhlili)

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);