Güman edək ki, — ağacın zirvəsidir. Aşağıdakıları qeyd edək:
dp_1(v) zirvə -dəki pulları götürdüyümüz halda, kökü olan alt ağacdan toplaya biləcəyimiz ən böyük pul məbləğidir.
dp_2(v) zirvə -dəki pulları götürmədiyimiz halda, kökü olan alt ağacdan toplaya biləcəyimiz ən böyük pul məbləğidir.
Beləliklə, problemi cavabı, zirvə -i ağacın kökü kimi qəbul etdikdə, max(dp_1(1), dp_2(1)) olacaq.
Tərtib olunan funksiyaları rekursiv olaraq təyin edək:
Zirvə -dəki pulları götürsək, onun oğlanlarından pulları götürmək olmaz:
Zirvə -dəki pulları götürməsək, oğlanlarından pulları ya götürmək, ya da götürməmək olar. Bu iki variantdan daha çox pul məbləği olan variantı seçmək lazımdır:
Əgər - c_v pulu olan bir yarpaqdırsa, onda funksiyalar aşağıdakı qiymətləri alacaq: dp_1(v) = c_v və dp_2(v) = 0.
Nümunə
Zirvələrdəki dp_1(v) / dp_2(v) etiketlərini qoyaq nümunələrin ağaclarına.
Birinci nümunə üçün:
dp_1(1) = c_1 + dp_2(2) + dp_2(3) = 1 + 3 + 0 = 4;
dp_2(1) = max(dp_1(2), dp_2(2)) + max(dp_1(3), dp_2(3)) = 5 + 7 = 12;
dp_1(2) = c_2 + dp_2(4) + dp_2(5) = 5 + 0 + 0 = 5;
dp_2(2) = max(dp_1(4), dp_2(4)) + max(dp_1(5), dp_2(5)) = 1 + 2 = 3;
İkinci nümunə üçün:
dp1(1) = c_1 + dp_2(2) + dp_2(3) = 3 + 11 + 0 = 14;
dp_2(1) = max(dp_1(2), dp_2(2)) + max(dp_1(3), dp_2(3)) = 11 + 5 = 16;
dp_1(2) = c_2 + dp_2(4) + dp_2(5) = 7 + 0 + 0 = 7;
dp_2(2) = max(dp_1(4), dp_2(4)) + max(dp_1(5), dp_2(5)) = 10 + 1 = 11;
Tapşırıq
Ağacın zirvələrində dp_1(v) / dp_2(v) etiketlərini qoyun:
Alqoritmin həyata keçirilməsi
İş səviyyələri elan edək.
vector<vector<int> > g;
vector<int> dp1, dp2, cost;dfs funksiyası dərinliyi axtarışı həyata keçirir. dp_1 və dp_2 qiymətlərini ağacın bütün zirvələrində hesablayaq.
void dfs(int v, int p = -1)
{
dp1[v] = cost[v];
dp2[v] = 0;
for (int to : g[v])
{
if (to == p) continue;
dfs(to, v);
dp1[v] += dp2[to];
dp2[v] += max(dp1[to], dp2[to]);
}
}Proqramın əsas hissəsi. Ağacı və pul səviyyəsini oxuyuruq.
scanf("%d",&n);
g.resize(n+1);
for(i = 1; i < n; i++)
{
scanf("%d %d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dp1.resize(n+1); dp2.resize(n+1);
cost.resize(n+1);
for(i = 1; i <= n; i++)
scanf("%d",&cost[i]);Tutaq ki, ağacın kökü zirvə -də yerləşir. Oradan dərindən axtarışa başlayırıq.
dfs(1);Cavabı hesablayırıq və çıxarırıq.
ans = max(dp1[1], dp2[1]);
printf("%d\n",ans);