2023.08.12-美团-第五题-树上染色

给定一棵树,每个节点都有一个权值以及最开始是白色。
定义操作A:
选择两个有边直接相连的节点,可以将两个节点同时染红.当且仅当他们都是白色
但是这样的题目太过简单,所以我们定义一个更复杂的操作B:
在满足操作A的条件下 两个节点的权值的乘积也需要是x∗x的形式 ,现在允许执行操作若干次操作B。问这棵树最多能够得到红色节点?

1. 动态规划树

#include"bits/stdc++.h"

using namespace std;


bool judge(long long x,long long y){
    long long i = sqrt(x*y);
    return x*y == i*i;
}


int main() {
    int n; cin>>n;
    vector<int> val(n+1);
    for(int i=1;i<=n;i++)
        cin>>val[i];
    vector<int> g[n+1];

    int from; int to;
    for(int i=0;i<n-1;i++){
        cin>>from>>to;
        g[from].push_back(to);
        g[to].push_back(from);
    }

    vector<vector<int>> memo(n+1,vector<int>(2,-1));//定义状态为第i个节点和上一节点不染和染的最大节点数
    function<int(int,bool,int)> dfs = [&](int i,bool j,int fa)->int{
        if(memo[i][j]!=-1) return memo[i][j];
        int not_dye = 0;
        int dye = (fa>0&&judge(val[i],val[fa]))?2:0;
        for (int x: g[i]) {//遍历子节点
            if (x == fa) continue;//跳过父节点
            dye+=dfs(x,0,i);//后面节点都不能染色
            int cur_not = max(dfs(x,0,i),dfs(x,1,i));//该节点可以选择染色与不染色,取最大值
            for(int y: g[i]){//其它子节点不染色,进行配对
                if(y == fa||y == x) continue;//跳过父节点和同一节点
                cur_not += dfs(y,0,i);//其它节点不染色
            }
            not_dye = max(not_dye,cur_not);
        }
        memo[i][0] = not_dye;
        memo[i][1] = dye;
        return memo[i][j];   
    };

    cout<<dfs(1,0,0);
    return 0;
};

posted @ 2023-11-05 21:32  失控D大白兔  阅读(55)  评论(0编辑  收藏  举报