牛客周賽 Round 8

udiandianis發表於2024-06-08

D 小美的樹上染色

題目描述

小美拿到了一棵樹,每個節點有一個權值。初始每個節點都是白色。
小美有若干次操作,每次操作可以選擇兩個相鄰的節點,如果它們都是白色且權值的乘積是完全平方數,小美就可以把這兩個節點同時染紅。
小美想知道,自己最多可以染紅多少個節點?

輸入描述

第一行輸入一個正整數\(n\),代表節點的數量。
第二行輸入\(n\)個正整數\(a_i\),代表每個節點的權值。
接下來的\(n-1\)行,每行輸入兩個正整數\(u,v\),代表節點\(u\)和節點\(v\)有一條邊連線。
\(1\leq n \leq 10^5\)
\(1\leq a_i \leq 10^9\)
\(1\leq u,v \leq n\)

輸出描述

輸出一個整數,表示最多可以染紅的節點數量。

解題思路

直接按照題意模擬,dfs暴力搜尋即可

程式碼實現

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
vector<int> g[N];
int st[N],w[N];
int ans;
void dfs(int u,int fa){
    for(auto x:g[u]){
        if(x==fa){
            continue;
        }
        dfs(x,u);
        if((int)sqrt(w[u]*w[x])*(int)sqrt(w[u]*w[x])==w[u]*w[x]&&(!st[x]&&!st[u])){//判斷染色條件
            ans+=2;
            st[x]=1;
            st[u]=1;
        }
    }
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i];//權值
    }
    for(int i=0;i<n-1;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,-1);
    cout<<ans;
    return 0;
}