计算树中的顶点对,使它们之间的距离是偶数
给定一棵有N个顶点的树,任务是找到顶点对的数量,使得它们之间的距离是偶数但不能为 0
例子:
Input: N = 5, Edges = [ [1, 0], [2, 1], [3, 1], [4, 3] ]
0
/
1
/ \
2 3
\
4
Output: 4
Explanation: There are four pairs of vertices such that the distance between them is even.
They are [ 0, 2 ], [0, 3], [3, 2] and [1, 4].
Input: N = 6, Edges: [[1, 0], [2, 1], [3, 1], [4, 2], [5, 3]]
0
/
1
/ \
2 3
/ /
4 5
Output: 6
Explanation: There are 6 pairs of vertices such that the distance between them is even. They are [0, 2], [4, 1], [3, 0], [4, 5], [1, 5] and [2, 3].
朴素方法:朴素方法是尝试所有可能的顶点对,找到它们之间的距离并检查距离是否相等。请按照以下步骤解决问题:
- 迭代i = 0 到 N-1的所有顶点:
- 从j = i+1 迭代到 N-1:
- 使用DFS查找从i到j的距离。
- 如果距离是偶数,则增加对数。
- 从j = i+1 迭代到 N-1:
- 返回计数。
下面是上述方法的实现。
C++
// C++ code to implement the approach
#include
using namespace std;
// Function to find the distance
void dfs(int i, int par,
vector >& adj,
vector& dis)
{
// Iterate over all the edges of vertex i
for (int j : adj[i]) {
// If 'j' is not the parent of 'i'.
if (j != par) {
// Store the distance
// from root till 'j'.
dis[j] = dis[i] + 1;
// Recurse for the child 'j'.
dfs(j, i, adj, dis);
}
}
}
// Function to count pairs
int countPairs(int n,
vector >& edges)
{
// Stores the final answer.
int ans = 0;
// Stores the adjacency List of the tree.
vector > adj(n);
for (int i = 0; i < n - 1; ++i) {
// Add the edge in the adjacency list.
adj[edges[i][0]].push_back(edges[i][1]);
adj[edges[i][1]].push_back(edges[i][0]);
}
// Stores the distance from root till 'i'.
vector dis(n);
// Iterate over all 'u'
// of the pair ('u', 'v').
for (int i = 0; i < n; ++i) {
// Set all the values
// of 'dis[i]' to '0'.
fill(dis.begin(), dis.end(), 0);
// Do a dfs with 'i' as
// the root of the tree.
dfs(i, -1, adj, dis);
// Iterate over the other end
// of the pair.
for (int j = i + 1; j < n; ++j) {
// If the distance is even.
if (dis[j] % 2 == 0) {
// Increment 'ans' by 1.
ans++;
}
}
}
// Return the answer 'ans'.
return ans;
}
// Driver Code
int main()
{
int N = 5;
vector > edges
= { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 3 } };
// Function call
cout << countPairs(N, edges);
return 0;
}
Javascript
C++
// C++ code to implement the approach
#include
using namespace std;
// Dfs function
void dfs(int i, int par,
vector >& adj,
vector& dis)
{
// Iterate over all edges of vertex 'i'.
for (int j : adj[i]) {
// If 'j' is not the parent of 'i'.
if (j != par) {
// Store the distance
// from root till 'j'.
dis[j] = dis[i] + 1;
// Recurse for the child 'j'.
dfs(j, i, adj, dis);
}
}
}
// Function to count the vertices
int countPairs(int n,
vector >& edges)
{
// Stores the adjacency List of the tree.
vector > adj(n);
for (int i = 0; i < n - 1; ++i) {
// Add the edge in the adjacency list.
adj[edges[i][0]].push_back(edges[i][1]);
adj[edges[i][1]].push_back(edges[i][0]);
}
// Stores the distance from root till 'i'.
vector dis(n);
// Dfs with '0' as the root of the tree.
dfs(0, -1, adj, dis);
// To store the size of set 'L'
// size of set 'R'.
int x = 0, y = 0;
// Iterate over all the vertices
// of the tree.
for (int i = 0; i < n; ++i) {
// If 'i' is at an even depth.
if (dis[i] % 2 == 0) {
// Increment the size of set 'L'.
x++;
}
else {
// Increment the size of set 'R'.
y++;
}
}
// Return the answer.
return x * (x - 1) / 2 + y * (y - 1) / 2;
}
// Driver Code
int main()
{
int N = 5;
vector > edges
= { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 3 } };
// Function call
cout << countPairs(N, edges);
return 0;
}
Python3
# python3 code to implement the approach
# Dfs function
def dfs(i, par, adj, dis):
# Iterate over all edges of vertex 'i'.
for j in adj[i]:
# If 'j' is not the parent of 'i'.
if (j != par):
# Store the distance
# from root till 'j'.
dis[j] = dis[i] + 1
# Recurse for the child 'j'.
dfs(j, i, adj, dis)
# Function to count the vertices
def countPairs(n, edges):
# Stores the adjacency List of the tree.
adj = [[] for _ in range(n)]
for i in range(0, n-1):
# Add the edge in the adjacency list.
adj[edges[i][0]].append(edges[i][1])
adj[edges[i][1]].append(edges[i][0])
# Stores the distance from root till 'i'.
dis = [0 for _ in range(n)]
# Dfs with '0' as the root of the tree.
dfs(0, -1, adj, dis)
# To store the size of set 'L'
# size of set 'R'.
x, y = 0, 0
# Iterate over all the vertices
# of the tree.
for i in range(0, n):
# If 'i' is at an even depth.
if (dis[i] % 2 == 0):
# Increment the size of set 'L'.
x += 1
else:
# Increment the size of set 'R'.
y += 1
# Return the answer.
return x * (x - 1) // 2 + y * (y - 1) // 2
# Driver Code
if __name__ == "__main__":
N = 5
edges = [[1, 0], [2, 1], [3, 1], [4, 3]]
# Function call
print(countPairs(N, edges))
# This code is contributed by rakeshsahni
4
时间复杂度:O(N 2 )
辅助空间:O(N)
有效方法:解决问题的有效方法是基于二分图的概念,如下所示。
Every tree is a bipartite graph. So all the vertices are part of one of the two bipartite sets (say L and R).
Any pair having both the values from different sets have an odd distance between them and pairs with vertices from the same set have even distance between them.
基于上述观察,很明显对的总数是使用来自同一集合的顶点形成的可能对,即( x C 2 ) + ( y C 2 ) ,其中 [ n C 2 = n * (n – 1)/2,x是集合L的大小,y是集合R]的大小。请按照以下步骤解决问题。
- 声明并初始化两个变量x和y为 0 以存储二分集的大小。
- 使 root 成为二分集之一的一部分(例如L )。
- 初始化一个数组(比如dis[] )来存储距离 0 的距离。
- 从顶点0开始一个 DFS 或 BFS:
- 在每一时刻,遍历所有的孩子,如果我们还没有访问过这个孩子(假设孩子是j ),那么:
- 将其距离增加为 dis[current node] = distance[parent] + 1。
- 如果是偶数,则增加x并使其成为集合 L 的一部分。否则,增加y并使其成为集合 R 的一部分。
- 递归地对其孩子做同样的事情。
- 在每一时刻,遍历所有的孩子,如果我们还没有访问过这个孩子(假设孩子是j ),那么:
- 最后,返回x C 2 + y C 2的值。
下面是上述方法的实现。
C++
// C++ code to implement the approach
#include
using namespace std;
// Dfs function
void dfs(int i, int par,
vector >& adj,
vector& dis)
{
// Iterate over all edges of vertex 'i'.
for (int j : adj[i]) {
// If 'j' is not the parent of 'i'.
if (j != par) {
// Store the distance
// from root till 'j'.
dis[j] = dis[i] + 1;
// Recurse for the child 'j'.
dfs(j, i, adj, dis);
}
}
}
// Function to count the vertices
int countPairs(int n,
vector >& edges)
{
// Stores the adjacency List of the tree.
vector > adj(n);
for (int i = 0; i < n - 1; ++i) {
// Add the edge in the adjacency list.
adj[edges[i][0]].push_back(edges[i][1]);
adj[edges[i][1]].push_back(edges[i][0]);
}
// Stores the distance from root till 'i'.
vector dis(n);
// Dfs with '0' as the root of the tree.
dfs(0, -1, adj, dis);
// To store the size of set 'L'
// size of set 'R'.
int x = 0, y = 0;
// Iterate over all the vertices
// of the tree.
for (int i = 0; i < n; ++i) {
// If 'i' is at an even depth.
if (dis[i] % 2 == 0) {
// Increment the size of set 'L'.
x++;
}
else {
// Increment the size of set 'R'.
y++;
}
}
// Return the answer.
return x * (x - 1) / 2 + y * (y - 1) / 2;
}
// Driver Code
int main()
{
int N = 5;
vector > edges
= { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 3 } };
// Function call
cout << countPairs(N, edges);
return 0;
}
Python3
# python3 code to implement the approach
# Dfs function
def dfs(i, par, adj, dis):
# Iterate over all edges of vertex 'i'.
for j in adj[i]:
# If 'j' is not the parent of 'i'.
if (j != par):
# Store the distance
# from root till 'j'.
dis[j] = dis[i] + 1
# Recurse for the child 'j'.
dfs(j, i, adj, dis)
# Function to count the vertices
def countPairs(n, edges):
# Stores the adjacency List of the tree.
adj = [[] for _ in range(n)]
for i in range(0, n-1):
# Add the edge in the adjacency list.
adj[edges[i][0]].append(edges[i][1])
adj[edges[i][1]].append(edges[i][0])
# Stores the distance from root till 'i'.
dis = [0 for _ in range(n)]
# Dfs with '0' as the root of the tree.
dfs(0, -1, adj, dis)
# To store the size of set 'L'
# size of set 'R'.
x, y = 0, 0
# Iterate over all the vertices
# of the tree.
for i in range(0, n):
# If 'i' is at an even depth.
if (dis[i] % 2 == 0):
# Increment the size of set 'L'.
x += 1
else:
# Increment the size of set 'R'.
y += 1
# Return the answer.
return x * (x - 1) // 2 + y * (y - 1) // 2
# Driver Code
if __name__ == "__main__":
N = 5
edges = [[1, 0], [2, 1], [3, 1], [4, 3]]
# Function call
print(countPairs(N, edges))
# This code is contributed by rakeshsahni
4
时间复杂度:O(N)
辅助空间:O(N)