牛客15天刷題ZT50_小美的樹上染色

栗悟饭与龟功気波發表於2024-11-29

小美的樹上染色

這是題面

思路

題目的限制條件有兩個

  1. 節點需要是相鄰的

  2. 都還沒被訪問過並且乘積是一個完全平方數

然後求最多能訪問多少個節點

如果從根開始考慮的話,可能不是很好想,因為跟可能有很多兒子,和哪個兒子結合呢?好像不好想

那我們可以試著從葉子節點開始考慮,因為葉子節點能夠結合的只有它們的父親

\(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;
}

相關文章