Count pairs of vertices in Tree such that distance between them is even
Last Updated :
15 Feb, 2023
Given a tree of N vertices, the task is to find the number of pairs of vertices such that the distance between them is even but cannot be 0
Examples:
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].
Naive Approach: The naive approach is to try all possible pairs of vertices, find the distance between them and check if the distance is even. Follow the steps mentioned below to solve the problem:
- Iterate over all the vertices for i = 0 to N-1:
- Iterate from j = i+1 to N-1:
- Find the distance from i to j using DFS.
- If the distance is even then increment the count of pairs.
- Return the count.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
void dfs( int i, int par,
vector<vector< int > >& adj,
vector< int >& dis)
{
for ( int j : adj[i]) {
if (j != par) {
dis[j] = dis[i] + 1;
dfs(j, i, adj, dis);
}
}
}
int countPairs( int n,
vector<vector< int > >& edges)
{
int ans = 0;
vector<vector< int > > adj(n);
for ( int i = 0; i < n - 1; ++i) {
adj[edges[i][0]].push_back(edges[i][1]);
adj[edges[i][1]].push_back(edges[i][0]);
}
vector< int > dis(n);
for ( int i = 0; i < n; ++i) {
fill(dis.begin(), dis.end(), 0);
dfs(i, -1, adj, dis);
for ( int j = i + 1; j < n; ++j) {
if (dis[j] % 2 == 0) {
ans++;
}
}
}
return ans;
}
int main()
{
int N = 5;
vector<vector< int > > edges
= { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 3 } };
cout << countPairs(N, edges);
return 0;
}
|
Java
import java.util.*;
public class Main
{
static void dfs( int i, int par,
ArrayList <ArrayList<Integer> > adj,
ArrayList <Integer> dis)
{
for ( int j : adj.get(i) ) {
if (j != par) {
dis.set(j, dis.get(i) + 1 );
dfs(j, i, adj, dis);
}
}
}
static int countPairs( int n,
int [][] edges)
{
int ans = 0 ;
ArrayList <ArrayList<Integer> > adj =
new ArrayList<ArrayList<Integer> >(n);
for ( int i = 0 ; i < n; i++)
adj.add( new ArrayList<Integer>());
for ( int i = 0 ; i < n - 1 ; ++i) {
adj.get(edges[i][ 0 ]).add(edges[i][ 1 ]);
adj.get(edges[i][ 1 ]).add(edges[i][ 0 ]);
}
for ( int i = 0 ; i < n; ++i) {
ArrayList <Integer> dis =
new ArrayList<Integer> (n);;
for ( int j = 0 ; j < n; ++j) {
dis.add( 0 );
}
dfs(i, - 1 , adj, dis);
for ( int j = i + 1 ; j < n; ++j) {
if (dis.get(j) % 2 == 0 ) {
ans++;
}
}
}
return ans;
}
public static void main(String args[])
{
int N = 5 ;
int [][] edges
= { { 1 , 0 }, { 2 , 1 }, { 3 , 1 }, { 4 , 3 } };
System.out.println( countPairs(N, edges) );
}
}
|
Python3
from typing import List , Tuple
def dfs(i: int , par: int , adj: List [ List [ int ]], dis: List [ int ]):
for j in adj[i]:
if j ! = par:
dis[j] = dis[i] + 1
dfs(j, i, adj, dis)
def countPairs(n: int , edges: List [ Tuple [ int , int ]]) - > int :
ans = 0
adj = [[] for i in range (n)]
for i in range (n - 1 ):
adj[edges[i][ 0 ]].append(edges[i][ 1 ])
adj[edges[i][ 1 ]].append(edges[i][ 0 ])
dis = [ 0 ] * n
for i in range (n):
dis = [ 0 ] * n
dfs(i, - 1 , adj, dis)
for j in range (i + 1 , n):
if dis[j] % 2 = = 0 :
ans + = 1
return ans
if __name__ = = "__main__" :
N = 5
edges = [( 1 , 0 ), ( 2 , 1 ), ( 3 , 1 ), ( 4 , 3 )]
print (countPairs(N, edges))
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static void dfs( int i, int par, List<List< int > > adj,
List< int > dis)
{
foreach ( int j in adj[i])
{
if (j != par)
{
dis[j] = dis[i] + 1;
dfs(j, i, adj, dis);
}
}
}
static int countPairs( int n, int [, ] edges)
{
int ans = 0;
List<List< int > > adj = new List<List< int > >(n);
for ( int i = 0; i < n; i++) {
adj.Add( new List< int >());
}
for ( int i = 0; i < n - 1; ++i)
{
adj[edges[i, 0]].Add(edges[i, 1]);
adj[edges[i, 1]].Add(edges[i, 0]);
}
for ( int i = 0; i < n; ++i) {
List< int > dis = new List< int >(n);
for ( int j = 0; j < n; ++j) {
dis.Add(0);
}
dfs(i, -1, adj, dis);
for ( int j = i + 1; j < n; ++j)
{
if (dis[j] % 2 == 0)
{
ans++;
}
}
}
return ans;
}
static public void Main()
{
int N = 5;
int [, ] edges
= { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 3 } };
Console.WriteLine(countPairs(N, edges));
}
}
|
Javascript
<script>
function dfs(i, par, adj, dis)
{
for (let j of adj[i]) {
if (j != par) {
dis[j] = dis[i] + 1;
dfs(j, i, adj, dis);
}
}
}
function countPairs(n,edges)
{
let ans = 0;
let adj = new Array(n);
for (let i=0;i<N;i++){
adj[i] = new Array();
}
for (let i = 0; i < n - 1; ++i) {
adj[edges[i][0]].push(edges[i][1]);
adj[edges[i][1]].push(edges[i][0]);
}
let dis = new Array(n);;
for (let i = 0; i < n; ++i) {
dis.fill(0);
dfs(i, -1, adj, dis);
for (let j = i + 1; j < n; ++j) {
if (dis[j] % 2 == 0) {
ans++;
}
}
}
return ans;
}
let N = 5;
let edges = [ [ 1, 0 ], [ 2, 1 ], [ 3, 1 ], [ 4, 3 ] ];
document.write(countPairs(N, edges));
</script>
|
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: The efficient approach to solve the problem is based on the concept of bipartite graph as shown below.
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.
Based on the above observation it is clear that the total number of pairs is the possible pairs formed using vertices from the same set i.e., (xC2) + (yC2), where [ nC2 = n * (n – 1)/2, x is the size of set L and y is the size of set R ]. Follow the steps mentioned below to solve the problem.
- Declare and initialize two variables x and y to 0 to store the size of the bipartite sets.
- Make root a part of one of the bipartite set (say L).
- Start a DFS or BFS from the vertex 0 and in the recursion keep track of its distance from the root:
- At each instant, iterate through all the children, and if we have not visited this child yet (let’s say the child is j), then:
- Increment the distance of the parent node to get the distance of the child.
- If it is even, increment x and make it part of set L. Otherwise, increment y and make it part of set R.
- Recursively do the same for its children.
- Finally, return the value of xC2 + yC2.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int x = 0, y = 0;
void dfs( int i, int par, vector<vector< int > >& adj, int dis)
{
if (dis % 2 == 0)
x++;
else
y++;
for ( int j : adj[i]) {
if (j != par) {
dfs(j, i, adj, dis+1);
}
}
}
int countPairs( int n, vector<vector< int > >& edges)
{
vector<vector< int > > adj(n);
for ( int i = 0; i < n - 1; ++i) {
adj[edges[i][0]].push_back(edges[i][1]);
adj[edges[i][1]].push_back(edges[i][0]);
}
dfs(0, -1, adj, 0);
return x * (x - 1) / 2 + y * (y - 1) / 2;
}
int main()
{
int N = 5;
vector<vector< int > > edges
= { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 3 } };
cout << countPairs(N, edges);
return 0;
}
|
Java
import java.util.*;
public class Main {
static int x = 0 , y = 0 ;
static void dfs( int i, int par,
ArrayList<ArrayList<Integer> > adj,
int dis)
{
if (dis % 2 == 0 )
x++;
else
y++;
for ( int j : adj.get(i)) {
if (j != par) {
dfs(j, i, adj, dis + 1 );
}
}
}
static int countPairs( int n, int [][] edges)
{
ArrayList<ArrayList<Integer> > adj
= new ArrayList<ArrayList<Integer> >(n);
for ( int i = 0 ; i < n; i++)
adj.add( new ArrayList<Integer>());
for ( int i = 0 ; i < n - 1 ; ++i) {
adj.get(edges[i][ 0 ]).add(edges[i][ 1 ]);
adj.get(edges[i][ 1 ]).add(edges[i][ 0 ]);
}
dfs( 0 , - 1 , adj, 0 );
return x * (x - 1 ) / 2 + y * (y - 1 ) / 2 ;
}
public static void main(String args[])
{
int N = 5 ;
int [][] edges
= { { 1 , 0 }, { 2 , 1 }, { 3 , 1 }, { 4 , 3 } };
System.out.println(countPairs(N, edges));
}
}
|
Python3
x, y = 0 , 0
def dfs(i, par, adj, dis):
global x
global y
if dis % 2 = = 0 :
x + = 1
else :
y + = 1
for j in adj[i]:
if (j ! = par):
dfs(j, i, adj, dis + 1 )
def countPairs(n, edges):
adj = [[] for _ in range (n)]
for i in range ( 0 , n - 1 ):
adj[edges[i][ 0 ]].append(edges[i][ 1 ])
adj[edges[i][ 1 ]].append(edges[i][ 0 ])
dfs( 0 , - 1 , adj, 0 )
return x * (x - 1 ) / / 2 + y * (y - 1 ) / / 2
if __name__ = = "__main__" :
N = 5
edges = [[ 1 , 0 ], [ 2 , 1 ], [ 3 , 1 ], [ 4 , 3 ]]
print (countPairs(N, edges))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG {
public static int x = 0;
public static int y = 0;
public static void dfs( int i, int par, LinkedList< int >[] adj, int dis)
{
if (dis % 2 == 0)
x++;
else
y++;
foreach ( var j in adj[i])
{
if (j != par){
dfs(j, i, adj, dis + 1);
}
}
}
public static int countPairs( int n, int [,] edges)
{
LinkedList< int >[] adj = new LinkedList< int >[n];
for ( int i = 0; i < n; i++)
adj[i] = new LinkedList< int >();
for ( int i = 0; i < n - 1; ++i) {
adj[edges[i,0]].AddLast(edges[i,1]);
adj[edges[i,1]].AddLast(edges[i,0]);
}
dfs(0, -1, adj, 0);
return x * (x - 1) / 2 + y * (y - 1) / 2;
}
static void Main() {
int N = 5;
int [,] edges = { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 3 } };
Console.WriteLine(countPairs(N, edges));
}
}
|
Javascript
let x = 0, y = 0;
function dfs(i, par, adj, dis)
{
if (dis % 2 === 0) {
x++;
} else {
y++;
}
adj[i].forEach(j => {
if (j !== par)
{
dfs(j, i, adj, dis + 1);
}
});
}
function countPairs(n, edges)
{
const adj = [];
for (let i = 0; i < n; i++) {
adj[i] = [];
}
for (let i = 0; i < n - 1; i++) {
adj[edges[i][0]].push(edges[i][1]);
adj[edges[i][1]].push(edges[i][0]);
}
dfs(0, -1, adj, 0);
return x * (x - 1) / 2 + y * (y - 1) / 2;
}
const N = 5;
const edges = [[1, 0], [2, 1], [3, 1], [4, 3]];
console.log(countPairs(N, edges));
|
Time Complexity: O(N)
Auxiliary Space: O(1) If the space for recursion call stack is considered then it is O(h) where h is the height of tree
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...