小美的樹上染色
這是題面
思路
題目的限制條件有兩個
-
節點需要是相鄰的
-
都還沒被訪問過並且乘積是一個完全平方數
然後求最多能訪問多少個節點
如果從根開始考慮的話,可能不是很好想,因為跟可能有很多兒子,和哪個兒子結合呢?好像不好想
那我們可以試著從葉子節點開始考慮,因為葉子節點能夠結合的只有它們的父親
\(dfs\)遍歷,回溯的時候看這個兒子能不能和父親結合,如果能結合肯定是要結合的,如果父親能和別的兒子結合,那麼結果和現在一樣,如果不能,現在就是最優,所以能結合就要結合,然後用\(vis\)陣列標記訪問過
程式碼
神奇的程式碼
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 1e5 + 5;
std::vector<int> tree[maxn];
int vis[maxn];
int val[maxn];
int ans = 0;
void dfs(int s, int fa)
{
for (int i = 0; i < tree[s].size(); i++)
{
int t = tree[s][i];
if(t == fa) continue;
dfs(t, s);
if (vis[t]) continue;
if (vis[s]) continue;
int tmp = val[s] * val[t];
int sq = sqrt(tmp);
if (sq * sq == tmp)
{
ans += 2;
vis[t] = 1;
vis[s] = 1;
}
}
}
void solve()
{
int n = 0;
std::cin >> n;
for (int i = 1; i <= n; i++)
{
std::cin >> val[i];
}
int u = 0, v = 0;
for (int i = 1; i <= n - 1; i++)
{
std::cin >> u >> v;
tree[u].push_back(v);
tree[v].push_back(u);
}
dfs(1, 0);
std::cout << ans << endl;
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
int t = 1;
// std::cin >> t;
while(t--)
{
solve();
}
return 0;
}