Maximize number of edges added to convert given Tree into a Bipartite Graph
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. |
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 |
1
Time Complexity: O(N)
Auxiliary Space: O(N)
Please Login to comment...