Open In App

Maximize number of edges added to convert given Tree into a Bipartite Graph

Last Updated : 31 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a tree of N nodes, the task is to find the maximum number of edges that can be added to the tree such that it becomes a bipartite graph.

Note: Self loop or multiple edges are not allowed but cycles are permitted.

Examples:

Input: N = 4, Edges = {{1, 2}, {2, 3}, {1, 4}}
              1
           /    \
        2       4
      /
   3
Output: 1
Explanation: An edge between nodes 3 and 4 can be added such that the graph still remains bipartite.
No more than 1 edge can be added such that the resultant graph is bipartite.

Input: N = 5, Edges = {{1, 2}, {1, 3}, {2, 4}, {2, 5}}
                      1
                   /    \
                2        3
            /     \
         4         5
Output: 2
Explanation: Two edges can be added, (3, 4) and (3, 5) and the graph still remains bipartite.

 

Naive Approach: The basic way to solve the problem is as follows:

Assign each node of the tree as black or white such that a black node is connected with a white node (There is always such a configuration because a tree is always bipartite).
Then for all possible pair of nodes check if an edge can be added between them.

Follow the steps mentioned below to implement the above idea:

  • Traverse the tree initially and assign each node as black or white such that each edge connects a black and a white node. (Trees are always bipartite).
  • Iterate over all pairs of nodes, and check if an edge can be added between them.
    • If both the nodes are of different colors and there is no edge between them, an edge can be added. So increment the count.
    • Otherwise, no edge can be added.
  • The final value of count is the answer.

Below is the implementation of the above approach. 

C++




// C++ code for the above approach:
 
#include <bits/stdc++.h>
using namespace std;
 
// DFS to mark nodes as black or white.
void dfs(int node, int par, bool isBlack,
         vector<vector<bool> >& adj,
         vector<bool>& color)
{
 
    // Mark color as black or white.
    color[node] = isBlack;
 
    for (int i = 1; i < adj.size(); ++i) {
 
        // If there is no edge,
        // or 'i' is parent, continue.
        if (!adj[node][i] || i == par)
            continue;
 
        dfs(i, node, !isBlack, adj, color);
    }
}
 
// Function to calculate
// maximum number of edges
// that can be added
long long maxEdges(int n,
                   vector<pair<int, int> > edges)
{
 
    // Build adjacency matrix.
    vector<vector<bool> > adj(n + 1,
                              vector<bool>(
                                  n + 1, 0));
    for (auto i : edges) {
        adj[i.first][i.second] = 1;
        adj[i.second][i.first] = 1;
    }
 
    // Call DFS to color nodes.
    vector<bool> color(n + 1);
    dfs(1, 0, 1, adj, color);
 
    long long ans = 0;
 
    // Iterate over all pairs of nodes.
    for (int i = 1; i <= n; ++i) {
        for (int j = i + 1; j <= n; ++j) {
 
            // If the color is different
            // And there is no edge
            // Between them, increment answer.
            if (color[i] != color[j]
                && !adj[i][j])
                ans++;
        }
    }
 
    // Return answer.
    return ans;
}
 
// Driver Code
int main()
{
    int N = 4;
    vector<pair<int, int> > edges
        = { { 1, 2 }, { 2, 3 }, { 1, 4 } };
    cout << maxEdges(N, edges);
    return 0;
}


Java




// Java code for the above approach:
import java.util.*;
 
public class Main {
  public static void main(String[] args)
  {
    int N = 4;
    List<List<Integer> > edges = new ArrayList<>();
    edges.add(Arrays.asList(1, 2));
    edges.add(Arrays.asList(2, 3));
    edges.add(Arrays.asList(1, 4));
    System.out.println(maxEdges(N, edges));
  }
  // Function to calculate
  // maximum number of edges
  // that can be added
  public static long maxEdges(int n,
                              List<List<Integer> > edges)
  {
    // Build adjacency matrix.
    boolean[][] adj = new boolean[n + 1][n + 1];
    for (int i = 0; i < edges.size(); ++i) {
      adj[edges.get(i).get(0)][edges.get(i).get(1)]
        = true;
      adj[edges.get(i).get(1)][edges.get(i).get(0)]
        = true;
    }
    // Call DFS to color nodes.
    boolean[] color = new boolean[n + 1];
    dfs(1, 0, true, adj, color);
 
    long ans = 0;
    // Iterate over all pairs of nodes.
    for (int i = 1; i <= n; ++i) {
      for (int j = i + 1; j <= n; ++j) {
        // If the color is different
        // And there is no edge
        // Between them, increment answer.
        if (color[i] != color[j] && !adj[i][j])
          ans++;
      }
    }
    // return ans
    return ans;
  }
  // DFS to mark nodes as black or white.
  public static void dfs(int node, int par,
                         boolean isBlack, boolean[][] adj,
                         boolean[] color)
  {
     
    // Mark color as black or white.
    color[node] = isBlack;
 
    for (int i = 1; i < adj.length; ++i)
    {
       
      // If there is no edge,
      // or 'i' is parent, continue.
      if (!adj[node][i] || i == par)
        continue;
 
      dfs(i, node, !isBlack, adj, color);
    }
  }
}
 
// This code is contributed by Tapesh(tapeshdua420)


Python3




#  Python code for the above approach:
 
# DFS to mark nodes as black or white.
def dfs(node, par, isBlack, adj, color):
 
  # Mark color as black or white.
    color[node] = isBlack
    for i in range(1, len(adj)):
        # If there is no edge,
         # or 'i' is parent, continue.
        if not adj[node][i] or i == par:
            continue
        dfs(i, node, not isBlack, adj, color)
 
# Function to calculate
# maximum number of edges
# that can be added
def maxEdges(n, edges):
   
  # Build adjacency matrix.
    adj = [[0 for _ in range(n + 1)] for _ in range(n + 1)]
    for i in edges:
        adj[i[0]][i[1]] = 1
        adj[i[1]][i[0]] = 1
 
    # Call DFS to color nodes.
    color = [0 for _ in range(n + 1)]
    dfs(1, 0, 1, adj, color)
 
    ans = 0
 
    # Iterate over all pairs of nodes.
    for i in range(1, n + 1):
        for j in range(i + 1, n + 1):
                # If the color is different
            # And there is no edge
            # Between them, increment answer.
            if color[i] != color[j] and not adj[i][j]:
                ans += 1
        # Return answer.
    return ans
 
 
# Driver Code
N = 4
edges = [[1, 2], [2, 3], [1, 4]]
print(maxEdges(N, edges))
 
# This code is contributed by tapeshdua420.


C#




// C# code for the above approach:
using System;
using System.Collections.Generic;
using System.Linq;
class Program {
    static void Main(string[] args)
    {
        int N = 4;
        List<Tuple<int, int> > edges
            = new List<Tuple<int, int> >(N);
        edges.Add(new Tuple<int, int>(1, 2));
        edges.Add(new Tuple<int, int>(2, 3));
        edges.Add(new Tuple<int, int>(1, 4));
        Console.WriteLine(maxEdges(N, edges));
    }
   
    // DFS to mark nodes as black or white.
    static void dfs(int node, int par, bool isBlack,
                    bool[, ] adj, bool[] color)
    {
       
        // Mark color as black or white.
        color[node] = isBlack;
 
        for (int i = 1; i < adj.GetLength(0); i++)
        {
           
            // If there is no edge,
            // or 'i' is parent, continue.
            if (adj[node, i] == false || i == par)
                continue;
            dfs(i, node, !isBlack, adj, color);
        }
    }
   
    // Function to calculate
    // maximum number of edges
    // that can be added
    static long maxEdges(int n,
                         List<Tuple<int, int> > edges)
    {
       
        // Build adjacency matrix.
        bool[, ] adj = new bool[n + 1, n + 1];
 
        foreach(Tuple<int, int> tuple in edges)
        {
            adj[tuple.Item1, tuple.Item2] = true;
            adj[tuple.Item2, tuple.Item1] = true;
        }
 
        // Call DFS to color nodes.
        bool[] color = new bool[n + 1];
        dfs(1, 0, true, adj, color);
 
        long ans = 0;
 
        // Iterate over all pairs of nodes.
        for (int i = 1; i <= n; ++i)
        {
            for (int j = i + 1; j <= n; ++j)
            {
               
                // If the color is different
                // And there is no edge
                // Between them, increment answer.
                if (color[i] != color[j]
                    && adj[i, j] == false)
                    ans++;
            }
        }
       
        // Return answer.
        return ans;
    }
}
 
// This code is contributed by tapeshdua420.


Javascript




// JavaScript code for the above approach:
 
// DFS to mark nodes as black or white.
const dfs = (node, par, isBlack, adj, color) => {
  // Mark color as black or white.
  color[node] = isBlack;
 
  for (let i = 1; i < adj.length; i++) {
// If there is no edge,
// or 'i' is parent, continue.
if (!adj[node][i] || i === par) continue;
 
dfs(i, node, !isBlack, adj, color);
  }
};
 
// Function to calculate
// maximum number of edges
// that can be added
const maxEdges = (n, edges) => {
  // Build adjacency matrix.
  const adj = Array.from({ length: n + 1 }, () =>
Array.from({ length: n + 1 }, () => 0)
  );
  edges.forEach(([a, b]) => {
adj[a][b] = 1;
adj[b][a] = 1;
  });
 
  // Call DFS to color nodes.
  const color = Array.from({ length: n + 1 }, () => false);
  dfs(1, 0, true, adj, color);
 
  let ans = 0;
 
  // Iterate over all pairs of nodes.
  for (let i = 1; i <= n; i++) {
for (let j = i + 1; j <= n; j++) {
    // If the color is different
    // And there is no edge
    // Between them, increment answer.
  if (color[i] !== color[j] && !adj[i][j]) ans++;
}
  }
 
  // Return answer.
  return ans;
};
 
// Driver Code
const N = 4;
const edges = [[1, 2], [2, 3], [1, 4]];
console.log(maxEdges(N, edges));
 
// This code is contributed by Aman Kumar.


Output

1

Time Complexity: O(N2)
Auxiliary Space: O(N2)

Efficient Approach: The time taken in the above approach can be optimized by using the following observation:

Say, there were initially B black nodes and W white nodes in the tree. So a bipartite graph made from these nodes can have maximum B*W edges.
Therefore, the maximum number of edges that can be added to the tree with N nodes are B*W – (N-1) [as a tree with N node has N-1 edges]

Follow the steps mentioned below:

  • Traverse the tree initially and assign each node as black or white such that each edge connects a black and a white node. (Trees are always bipartite).
  • Count the number of black nodes and white nodes.
  • Use the formula derived above from the observation and calculate the maximum number of edges that can be added.

Below is the implementation of the above approach.

C++




// C++ code for the above approach:
 
#include <bits/stdc++.h>
using namespace std;
 
// DFS to count number of black nodes.
int dfs(int node, int par, bool isBlack,
        vector<vector<int> >& adj)
{
    int no_Of_Black = isBlack;
    for (int i : adj[node]) {
        if (i == par)
            continue;
 
        // Number of black nodes
        // in each subtree.
        no_Of_Black
            += dfs(i, node, !isBlack, adj);
    }
    return no_Of_Black;
}
 
// Function to find maximum edges
long long maxEdges(int n,
                   vector<pair<int, int> > edges)
{
 
    // Build adjacency list.
    vector<vector<int> > adj(n + 1);
    for (auto i : edges) {
        adj[i.first].push_back(i.second);
        adj[i.second].push_back(i.first);
    }
 
    // Number of black nodes.
    int no_Of_Black = dfs(1, 0, 1, adj);
 
    // Number of white nodes.
    int no_Of_White = n - no_Of_Black;
 
    // Number of edges that can be added.
    return (1LL * (no_Of_Black)
                * (no_Of_White)
            - (n - 1));
}
 
// Driver code
int main()
{
    int N = 4;
    vector<pair<int, int> > edges
        = { { 1, 2 }, { 2, 3 }, { 1, 4 } };
    cout << maxEdges(N, edges);
    return 0;
}


Java




// Java code for the above approach:
import java.util.*;
 
public class Main
{
 
  // Driver code
  public static void main(String[] args)
  {
    int N = 4;
    int[][] edges = { { 1, 2 }, { 2, 3 }, { 1, 4 } };
    System.out.println(maxEdges(N, edges));
  }
 
  // Function to find maximum edges
  public static long maxEdges(int n, int[][] edges)
  {
    // Build adjacency list.
    List<List<Integer> > adj = new ArrayList<>();
    for (int i = 0; i <= n; i++) {
      adj.add(new ArrayList<>());
    }
    for (int[] edge : edges) {
      adj.get(edge[0]).add(edge[1]);
      adj.get(edge[1]).add(edge[0]);
    }
    // Number of black nodes.
    int no_Of_Black = dfs(1, 0, true, adj);
 
    // Number of white nodes.
    int no_Of_White = n - no_Of_Black;
 
    // Number of edges that can be added.
    return ((no_Of_Black) * (no_Of_White) - (n - 1));
  }
 
  // DFS to count number of black nodes.
  public static int dfs(int node, int par,
                        boolean isBlack,
                        List<List<Integer> > adj)
  {
 
    int no_Of_Black = (isBlack == true) ? 1 : 0;
 
    for (int i : adj.get(node)) {
 
      if (i == par)
        continue;
 
      // Number of black nodes
      // in each subtree.
      no_Of_Black += dfs(i, node, !isBlack, adj);
    }
    return no_Of_Black;
  }
}
 
// This code is contributed by Tapesh(tapeshdua420)


Python3




## DFS to count number of black nodes.
def dfs(node, par, isBlack, adj) :
    no_of_black = isBlack
    for i in adj[node]:
        if(i==par):
            continue
         
        ## Number of black nodes
        ## in each subtree.
        no_of_black += dfs(i, node, (not isBlack), adj)
 
    return no_of_black
 
 
def maxEdges(n, edges):
    adj = []
     
    for i in range(n+1):
        adj.append(list())
     
    ## Create the graph
    ## From the given input.
    for i in edges:
        adj[i[0]].append(i[1])
        adj[i[1]].append(i[0])
 
    ## Number of black nodes.
    no_of_black = dfs(1, 0, 1, adj)
 
    ## Number of white nodes.
    no_of_white = n - no_of_black
 
    ## Number of edges that can be added.
    return (no_of_black*no_of_white) - (n-1)
     
# Driver Code
if __name__ == "__main__":
 
    N = 4
    edges = list((list((1, 2)), list((2, 3)), list((1, 4))))
 
    print(maxEdges(N, edges))
     
    # This code is contributed by subhamgoyal2014.


C#




// C# code for the above approach:
using System;
using System.Collections.Generic;
 
class Program {
 
  // Driver code
  static void Main(string[] args)
  {
 
    int N = 4;
 
    int[][] edges
      = { new int[] { 1, 2 }, new int[] { 2, 3 },
         new int[] { 1, 4 } };
 
    Console.WriteLine(maxEdges(N, edges));
  }
 
  // Function to find maximum edges
  static long maxEdges(int n, int[][] edges)
  {
 
    // Build adjacency list.
    List<List<int> > adj = new List<List<int> >();
 
    for (int i = 0; i <= n; i++) {
      adj.Add(new List<int>());
    }
 
    foreach(int[] edge in edges)
    {
 
      adj[edge[0]].Add(edge[1]);
 
      adj[edge[1]].Add(edge[0]);
    }
 
    // Number of black nodes.
    int no_Of_Black = dfs(1, 0, true, adj);
 
    // Number of white nodes.
    int no_Of_White = n - no_Of_Black;
 
    // Number of edges that can be added.
    return ((no_Of_Black) * (no_Of_White) - (n - 1));
  }
 
  // DFS to count number of black nodes.
  static int dfs(int node, int par, bool isBlack,
                 List<List<int> > adj)
  {
 
    int no_Of_Black = (isBlack == true) ? 1 : 0;
 
    foreach(int i in adj[node])
    {
 
      if (i == par)
        continue;
 
      // Number of black nodes
      // in each subtree.
      no_Of_Black += dfs(i, node, !isBlack, adj);
    }
    return no_Of_Black;
  }
}
 
// This code is contributed by Tapesh (tapeshdua420)


Javascript




       // JavaScript code for the above approach
       // DFS to count number of black nodes.
       function dfs(node, par, isBlack, adj) {
           let no_Of_Black = isBlack ? 1 : 0;
           for (let i of adj[node]) {
               if (i == par) continue;
 
               // Number of black nodes
               // in each subtree.
               no_Of_Black += dfs(i, node, !isBlack, adj);
           }
           return no_Of_Black;
       }
 
       // Function to find maximum edges
       function maxEdges(n, edges) {
           // Build adjacency list.
           let adj = new Array(n + 1);
           for (let i = 0; i <= n; i++) {
               adj[i] = [];
           }
           for (let i of edges) {
               adj[i[0]].push(i[1]);
               adj[i[1]].push(i[0]);
           }
 
           // Number of black nodes.
           let no_Of_Black = dfs(1, 0, true, adj);
 
           // Number of white nodes.
           let no_Of_White = n - no_Of_Black;
 
           // Number of edges that can be added.
           return no_Of_Black * no_Of_White - (n - 1);
       }
 
       // Driver code
       let N = 4;
       let edges = [[1, 2], [2, 3], [1, 4]];
       console.log(maxEdges(N, edges));
 
// This code is contributed by Potta Lokesh


Output

1

Time Complexity: O(N)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads