贪心,DFS:小美的树上染色

简介: 贪心,DFS:小美的树上染色

题目描述

小美拿到了一棵树,每个节点有一个权值。初始每个节点都是白色。小美有若干次操作,每次操作可以选择两个相邻的节点,如果它们都是白色且权值的乘积是完全平方数,小美就可以把这两个节点同时染红。小美想知道,自己最多可以染红多少个节点?

输入描述:第一行输入一个正整数n,代表节点的数量。 第二行输入n个正整数ai,代表每个节点的权值。 接下来的n−1行,每行输入两个正整数u,v,代表节点u和节点v有一条边连接。1≤n≤10^5 1≤ai≤10^9 ,1≤u,v≤n。

输出描述:输出一个整数,表示最多可以染红的节点数量。

输入

3

3 3 12

1 2

2 3

输出

2

说明:可以染红第二个和第三个节点。请注意,此时不能再染红第一个和第二个节点,因为第二个节点已经被染红。因此,最多染红 2 个节点。

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int N=1e6+5;
inline int read(){
  int x=0;
    char c=getchar();
  while(c<'0'||c>'9')
        c=getchar();
  while(c>='0'&&c<='9')
        x=(x<<3)+(x<<1)+(c^48),c=getchar();
  return x;
}
int a[N],f[N][2];
vector<int>g[N];
void dfs(int x,int y){
  vector<int>ve;
  int k=0,s=0;
  for(int i:g[x]){
    if(i==y)
            continue;
    dfs(i,x);
    int sq=sqrt(a[x]*a[i]);
    if(sq*sq==a[x]*a[i])ve.push_back(i);
    s+=max(f[i][1],f[i][0]);
  }
  f[x][0]=s;
  for(int i:ve){
    f[x][1]=max(f[x][1],s-max(f[i][1],f[i][0])+f[i][0]+2);
  }
}
int  main(){
  int n=read();
  for(int i=1;i<=n;++i)a[i]=read();
  for(int i=1;i<n;++i){
    int u=read(),v=read();
    g[u].push_back(v);
    g[v].push_back(u);
  }
  dfs(1,0);
  cout<<max(f[1][0],f[1][1]);
}

 

  1. const int N=1e6+5;:定义一个常量N,表示图中顶点的最大数量。
  2. inline int read():定义一个内联函数read,用于读取一个整数,内联函数使运行效率高。
  3. int a[N],f[N][2];:定义两个数组afa用于存储每个顶点的值,f是一个二维数组,用于存储每个顶点的两个不同状态的值。
  4. vector<int>g[N];:定义一个邻接表g,表示图的邻接关系。
  5. void dfs(int x,int y):定义一个深度优先搜索函数dfsx是当前顶点,y是上一个顶点。
  6. dfs函数中,首先初始化一个空的vector ve,两个整数ks
  7. 使用循环遍历当前顶点x的所有邻接顶点,如果邻接顶点是上一个顶点y,则跳过。
  8. 对每个邻接顶点i,递归调用dfs(i,x)
  9. 计算当前顶点x和邻接顶点i的乘积的平方根,如果平方根的平方等于原始乘积,则将i加入到ve中。
  10. 更新s为当前顶点所有子树中最大值的最大值。
  11. 更新f[x][0]s
  12. 循环遍历ve中的每个顶点i,更新f[x][1]为当前f[x][1]s减去i的较大值加上i的较小值再加2的最大值。
  13. 读取顶点的数量n
  14. 循环读取每个顶点的值,并存储在数组a中。
  15. 循环读取每条边的信息,构建图的邻接表。
  16. 从顶点1开始调用dfs函数。
  17. 输出f[1][0]f[1][1]中的较大值。

找到树中最长的简单路径,f[x][0]表示以x为根的子树中,不包含直径的最大边权和,而f[x][1]表示包含直径的最大边权和。最终输出的是整个树中最长路径的边权和。


目录
相关文章
|
4月前
|
算法 图计算
心得经验总结:无向图:计算亏格(环的孔洞)
心得经验总结:无向图:计算亏格(环的孔洞)
22 0
|
4月前
|
存储 算法 数据可视化
LeetCode 130题详解:深度优先搜索与广度优先搜索解决被围绕的区域
LeetCode 130题详解:深度优先搜索与广度优先搜索解决被围绕的区域
|
4月前
|
搜索推荐 Java
单源最短路(只有一个起点)bfs,多源BFS,目录力扣675.为高尔夫比赛砍树,多源最短路问题:力扣542.01矩阵力扣1020.飞地的数量
单源最短路(只有一个起点)bfs,多源BFS,目录力扣675.为高尔夫比赛砍树,多源最短路问题:力扣542.01矩阵力扣1020.飞地的数量
|
5月前
|
机器学习/深度学习 算法 测试技术
【单源最短路 图论】882. 细分图中的可到达节点
【单源最短路 图论】882. 细分图中的可到达节点
|
5月前
|
算法 测试技术 C#
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
|
5月前
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树2
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树2
|
5月前
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树1
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树
|
5月前
|
算法 测试技术 C#
【深度优化】【广度优先】【状态压缩】864. 获取所有钥匙的最短路径
【深度优化】【广度优先】【状态压缩】864. 获取所有钥匙的最短路径
|
5月前
|
机器学习/深度学习 测试技术
【图论】【状态压缩】【树】【深度优先搜索】1617. 统计子树中城市之间最大距离
【图论】【状态压缩】【树】【深度优先搜索】1617. 统计子树中城市之间最大距离
|
5月前
|
算法 测试技术 C++
【广度优先搜索】【拓扑排序】【C++算法】913. 猫和老鼠
【广度优先搜索】【拓扑排序】【C++算法】913. 猫和老鼠