Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

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

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

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)


My Personal Notes arrow_drop_up
Last Updated : 31 Jan, 2023
Like Article
Save Article
Similar Reads
Related Tutorials