给定一个包含N 个节点和两个节点u和v的加权树,任务是在u 和 v之间的简单路径上找到具有素数权重的节点数(两者都包括在内) 。
例子:
Input:
u = 3, v = 5
Output: 2
Explanation:
Prime weight on path 3 to 5 is [11, 5]. Hence, the answer is 2.
方法:解决上面提到的问题,思路是用我们求两个节点的LCA时的基本概念。
- 使用 Sieve 方法预先计算所有素数直到 MAX,以在 O(1) 中检查数字是否为素数
- 给定两个节点 u 和 v,通过向上移动更高级别的节点,我们将使两个节点处于同一级别。随着我们向上移动,我们还将检查权重是否为素数。
- 如果v == u那么我们将简单地检查当前节点的权重并返回计数。
- 如果v 不等于 u,那么我们将u 和 v 向上移动 1,直到它们不相同。
- 现在我们将最终检查 u 或 v 的第一个祖先的权重并返回计数。
下面是上述方法的实现:
C++
// C++ program Count prime weight
// nodes between two nodes in the given tree
#include
using namespace std;
#define MAX 1000
int weight[MAX];
int level[MAX];
int par[MAX];
bool prime[MAX + 1];
vector graph[MAX];
// Function to perform
// Sieve Of Eratosthenes for prime number
void SieveOfEratosthenes()
{
// Initialize all entries of prime it as true
// A value in prime[i] will finally be false
// if i is Not a prime, else true.
memset(prime, true, sizeof(prime));
for (int p = 2; p * p <= MAX; p++) {
// Check if prime[p] is not changed,
// then it is a prime
if (prime[p] == true) {
// Update all multiples
// of p greater than or
// equal to the square of it
// numbers which are multiple
// of p and are less than p^2
// are already been marked.
for (int i = p * p; i <= MAX; i += p)
prime[i] = false;
}
}
}
// Function to perform dfs
void dfs(int node, int parent, int h)
{
// Stores parent of each node
par[node] = parent;
// Stores level of each node from root
level[node] = h;
for (int child : graph[node]) {
if (child == parent)
continue;
dfs(child, node, h + 1);
}
}
// Function to perform prime
// number between the path
int findPrimeOnPath(int u, int v)
{
int count = 0;
// The node which is present farthest
// from the root node is taken as v
// If u is farther from root node
// then swap the two
if (level[u] > level[v])
swap(u, v);
int d = level[v] - level[u];
// Find the ancestor of v
// which is at same level as u
while (d--) {
// If Weight is prime
// increment count
if (prime[weight[v]])
count++;
v = par[v];
}
// If u is the ancestor of v
// then u is the LCA of u and v
// Now check if weigh[v]
// is prime or not
if (v == u) {
if (prime[weight[v]])
count++;
return count;
}
// When v and u are on the same level but
// are in different subtree. Now move both
// u and v up by 1 till they are not same
while (v != u) {
if (prime[weight[v]])
count++;
if (prime[weight[u]])
count++;
u = par[u];
v = par[v];
}
// If weight of first ancestor
// is prime
if (prime[weight[v]])
count++;
return count;
}
// Driver code
int main()
{
// Precompute all the prime
// numbers till MAX
SieveOfEratosthenes();
// Weights of the node
weight[1] = 5;
weight[2] = 10;
weight[3] = 11;
weight[4] = 8;
weight[5] = 6;
// Edges of the tree
graph[1].push_back(2);
graph[2].push_back(3);
graph[2].push_back(4);
graph[1].push_back(5);
dfs(1, -1, 0);
int u = 3, v = 5;
cout << findPrimeOnPath(u, v)
<< endl;
return 0;
}
Java
// Java program to count
// prime weight nodes
// between two nodes
// in the given tree
import java.util.*;
class GFG{
static final int MAX = 1000;
static int []weight =
new int[MAX];
static int []level =
new int[MAX];
static int []par =
new int[MAX];
static boolean []prime =
new boolean[MAX + 1];
static Vector[] graph =
new Vector[MAX];
// Function to perform
// Sieve Of Eratosthenes
// for prime number
static void SieveOfEratosthenes()
{
// Initialize all entries of
// prime it as true a value in
// prime[i] will finally be false
// if i is Not a prime, else true.
for (int i = 0;
i < prime.length; i++)
prime[i] = true;
for (int p = 2;
p * p <= MAX; p++)
{
// Check if prime[p]
// is not changed,
// then it is a prime
if (prime[p] == true)
{
// Update all multiples
// of p greater than or
// equal to the square of it
// numbers which are multiple
// of p and are less than p^2
// are already been marked.
for (int i = p * p;
i <= MAX; i += p)
prime[i] = false;
}
}
}
// Function to perform dfs
static void dfs(int node,
int parent, int h)
{
// Stores parent of each node
par[node] = parent;
// Stores level of each
// node from root
level[node] = h;
for (int child : graph[node])
{
if (child == parent)
continue;
dfs(child, node, h + 1);
}
}
// Function to perform prime
// number between the path
static int findPrimeOnPath(int u,
int v)
{
int count = 0;
// The node which is present
// farthest from the root
// node is taken as v
// If u is farther from
// root node then swap the two
if (level[u] > level[v])
{
int temp = v;
v = u;
u = temp;
}
int d = level[v] - level[u];
// Find the ancestor of v
// which is at same level as u
while (d-- > 0)
{
// If Weight is prime
// increment count
if (prime[weight[v]])
count++;
v = par[v];
}
// If u is the ancestor of v
// then u is the LCA of u and v
// Now check if weigh[v]
// is prime or not
if (v == u)
{
if (prime[weight[v]])
count++;
return count;
}
// When v and u are on the
// same level but are in
// different subtree. Now
// move both u and v up by
// 1 till they are not same
while (v != u)
{
if (prime[weight[v]])
count++;
if (prime[weight[u]])
count++;
u = par[u];
v = par[v];
}
// If weight of first
// ancestor is prime
if (prime[weight[v]])
count++;
return count;
}
// Driver code
public static void main(String[] args)
{
for (int i = 0; i < graph.length; i++)
graph[i] = new Vector();
// Precompute all the prime
// numbers till MAX
SieveOfEratosthenes();
// Weights of the node
weight[1] = 5;
weight[2] = 10;
weight[3] = 11;
weight[4] = 8;
weight[5] = 6;
// Edges of the tree
graph[1].add(2);
graph[2].add(3);
graph[2].add(4);
graph[1].add(5);
dfs(1, -1, 0);
int u = 3, v = 5;
System.out.print(findPrimeOnPath(u, v));
}
}
// This code is contributed by shikhasingrajput
Python3
# Python3 program count prime weight
# nodes between two nodes in the given tree
MAX = 1000
weight = [0 for i in range(MAX)]
level = [0 for i in range(MAX)]
par = [0 for i in range(MAX)]
prime = [True for i in range(MAX + 1)]
graph = [[] for i in range(MAX)]
# Function to perform
# Sieve Of Eratosthenes
# for prime number
def SieveOfEratosthenes():
# Initialize all entries of prime it
# as true. A value in prime[i] will
# finally be false if i is Not a prime,
# else true. memset(prime, true,
# sizeof(prime))
for p in range(2, MAX + 1):
if p * p > MAX + 1:
break
# Check if prime[p] is not changed,
# then it is a prime
if (prime[p] == True):
# Update all multiples
# of p greater than or
# equal to the square of it
# numbers which are multiple
# of p and are less than p^2
# are already been marked.
for i in range(p * p, MAX + 1, p):
prime[i] = False
# Function to perform dfs
def dfs(node, parent, h):
# Stores parent of each node
par[node] = parent
# Stores level of each node from root
level[node] = h
for child in graph[node]:
if (child == parent):
continue
dfs(child, node, h + 1)
# Function to perform prime
# number between the path
def findPrimeOnPath(u, v):
count = 0
# The node which is present farthest
# from the root node is taken as v
# If u is farther from root node
# then swap the two
if (level[u] > level[v]):
u, v = v, u
d = level[v] - level[u]
# Find the ancestor of v
# which is at same level as u
while (d):
# If Weight is prime
# increment count
if (prime[weight[v]]):
count += 1
v = par[v]
d -= 1
# If u is the ancestor of v
# then u is the LCA of u and v
# Now check if weigh[v]
# is prime or not
if (v == u):
if (prime[weight[v]]):
count += 1
return count
# When v and u are on the same level but
# are in different subtree. Now move both
# u and v up by 1 till they are not same
while (v != u):
if (prime[weight[v]]):
count += 1
if (prime[weight[u]]):
count += 1
u = par[u]
v = par[v]
# If weight of first ancestor
# is prime
if (prime[weight[v]]):
count += 1
return count
# Driver code
if __name__ == '__main__':
# Precompute all the prime
# numbers till MAX
SieveOfEratosthenes()
# Weights of the node
weight[1] = 5
weight[2] = 10
weight[3] = 11
weight[4] = 8
weight[5] = 6
# Edges of the tree
graph[1].append(2)
graph[2].append(3)
graph[2].append(4)
graph[1].append(5)
dfs(1, -1, 0)
u = 3
v = 5
print(findPrimeOnPath(u, v))
# This code is contributed by mohit kumar 29
C#
// C# program to count prime weight
// nodes between two nodes in the
// given tree
using System;
using System.Collections.Generic;
class GFG{
static readonly int MAX = 1000;
static int []weight = new int[MAX];
static int []level = new int[MAX];
static int []par = new int[MAX];
static bool []prime = new bool[MAX + 1];
static List[] graph = new List[MAX];
// Function to perform
// Sieve Of Eratosthenes
// for prime number
static void SieveOfEratosthenes()
{
// Initialize all entries of
// prime it as true a value in
// prime[i] will finally be false
// if i is Not a prime, else true.
for(int i = 0;
i < prime.Length; i++)
prime[i] = true;
for(int p = 2;
p * p <= MAX; p++)
{
// Check if prime[p]
// is not changed,
// then it is a prime
if (prime[p] == true)
{
// Update all multiples
// of p greater than or
// equal to the square of it
// numbers which are multiple
// of p and are less than p^2
// are already been marked.
for(int i = p * p;
i <= MAX; i += p)
prime[i] = false;
}
}
}
// Function to perform dfs
static void dfs(int node, int parent,
int h)
{
// Stores parent of each node
par[node] = parent;
// Stores level of each
// node from root
level[node] = h;
foreach(int child in graph[node])
{
if (child == parent)
continue;
dfs(child, node, h + 1);
}
}
// Function to perform prime
// number between the path
static int findPrimeOnPath(int u,
int v)
{
int count = 0;
// The node which is present
// farthest from the root
// node is taken as v
// If u is farther from
// root node then swap the two
if (level[u] > level[v])
{
int temp = v;
v = u;
u = temp;
}
int d = level[v] - level[u];
// Find the ancestor of v
// which is at same level as u
while (d-- > 0)
{
// If Weight is prime
// increment count
if (prime[weight[v]])
count++;
v = par[v];
}
// If u is the ancestor of v
// then u is the LCA of u and v
// Now check if weigh[v]
// is prime or not
if (v == u)
{
if (prime[weight[v]])
count++;
return count;
}
// When v and u are on the
// same level but are in
// different subtree. Now
// move both u and v up by
// 1 till they are not same
while (v != u)
{
if (prime[weight[v]])
count++;
if (prime[weight[u]])
count++;
u = par[u];
v = par[v];
}
// If weight of first
// ancestor is prime
if (prime[weight[v]])
count++;
return count;
}
// Driver code
public static void Main(String[] args)
{
for(int i = 0; i < graph.Length; i++)
graph[i] = new List();
// Precompute all the prime
// numbers till MAX
SieveOfEratosthenes();
// Weights of the node
weight[1] = 5;
weight[2] = 10;
weight[3] = 11;
weight[4] = 8;
weight[5] = 6;
// Edges of the tree
graph[1].Add(2);
graph[2].Add(3);
graph[2].Add(4);
graph[1].Add(5);
dfs(1, -1, 0);
int u = 3, v = 5;
Console.Write(findPrimeOnPath(u, v));
}
}
// This code is contributed by Amit Katiyar
Javascript
输出:
2
复杂度分析:
- 时间复杂度: O(N)。
在 dfs 中,树的每个节点都被处理一次,因此如果树中总共有 N 个节点,则由 dfs 引起的复杂度为 O(N)。此外,为了处理每个节点,使用了 SieveOfEratosthenes()函数,它也具有 O(sqrt(N)) 的复杂度,但由于该函数仅执行一次,因此不会影响整体时间复杂度。因此,时间复杂度为 O(N)。 - 辅助空间: O(N)。
额外的空间用于素数数组,因此空间复杂度为 O(N)。
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live