Given an integer N denoting the total number of fights between empire A and B all together in a war zone, also given a 2-D array arr of size N denoting that soldier arr[i][0] and arr[i][1] are fighting with each other. The task is to find the maximum number of soldiers belonging to an empire if it is possible to distribute all the soldiers among A and B, otherwise print -1.
Example:
Input: N = 4, arr = [[1, 2], [2, 3], [2, 4], [2, 5]]
Output: 4
Explanation: From the input we have following fight:
{1, 3, 4, 6} fighting with {2} => maximum group of soldier = 4.Input: N = 8, arr = [[1, 2], [2, 3], [3, 4], [3, 5], [6, 7], [7, 8], [7, 9], [7, 10]]
Output: 7
Explanation: From the input we have following fights:
{1, 3} fighting with {2, 4, 5} => maximum group of soldier=3
{6, 8, 9, 10} fighting with {7} => maximum group of soldier=4
Hence maximum number of soldier in an empire = 3+4 = 7Input: N=3, arr=[[1, 2], [2, 3], [3, 1]]
Output: -1
Explanation: it is impossible to distribute 1, 2 and 3 among A and B such that there is not a fight between soldier of same empire.
Approach: Using a Bipartite graph to solve the question as discussed below:
We can create a graph from the array ‘arr‘ such that there is a bidirectional edge between arr[i][0] and arr[i][1] , then apply the Bipartite coloring on each component of the graph.
To get the answer pick the occurrence of the maximum occurring color of each component of the graph and add them together.
If in case for any component we can not color it using Bipartite coloring, then we return -1.
Illustration:
Lets suppose, N=8, arr=[[1, 2],[1, 3],[1, 4],[1, 5],[2, 6],[3, 6],[4, 6],[5, 6]]
To solve this test case, firstly we can create a graph such that there is a bidirectional edge between arr[i][0] and arr[i][1] as shown in fig-1.
After applying Bipartite coloring on the graph (as shown in fig-1) we see that vertex {1, 6} have same color(blue) and vertex {2, 3, 4, 5} have same color(yellow). Since the frequency of Yellow color is more i.e. 4>2, hence for this graph we can conclude that maximum 4 number of soldier are in same team and return 4 as our answer.
Now let’s see a case when grouping of soldier into two empiers is immpossible and we return -1 as our answer. Suppose N=5, arr=[[1, 2],[2, 3],[3, 4],[4, 5],[5, 1]]
In this test case when when we apply Bipartite coloring (say on vertex 1) there will be 2 cases of coloring possible:
Case 1: node 4 and node 5 have same color and an edge between them.
Case 2: node 4 and node 3 have same color and an edge between them.
Both these cases are contradicting the Bipartite coloring and hence we return -1. In short Bipartite coloring is impossible for a graph having an odd length cycle. This case is clearly shown in fig-2.
Follow the steps to solve the problem:
- Create a graph ‘g‘ such that arr[i][0] and arr[i][1] are vertices of that graph.
- Keep track of all unique vertices in an array of ‘soldiers[]‘.
- Create a ‘colr[]‘ array initialized by ‘-1′ to keep track of the color of each vertex.
- Now apply Bipartite coloring on all the vertices which are not colored yet. For each component of the graph find the maximum occurrence of the color i.e. max(zero, one) (Note: zero and one represent two colors) and add that value to the answer ‘ans‘.
- In case Bipartite coloring is not possible for any component set the ‘flag’ variable as false and return ‘-1′.
Below is the implementation of the above algorithm:
// C++ code for the above approach #include <bits/stdc++.h> using namespace std;
// one and zero are our two colors int one, zero;
// Flag to check whether the answer // exists or not bool flag = true ;
void BipartiteColor( int v, vector<vector< int > >& g,
vector< int >& colr, int paint)
{ // if the vertex is already colored
if (colr[v] != -1) {
// if previous color and current paint
// contradict each other then our answer
// won't exist
if (colr[v] != paint)
flag = false ;
return ;
}
// paint the current vertex v
colr[v] = paint;
// if paint is 1
if (paint)
one++;
// if paint is 0
else
zero++;
// Recursive calls on the child of vertex v
for ( auto child : g[v]) {
// Giving the complementory color to the
// child i.e. if colr[v]=1 then
// colr[child]=0 and vice verse
BipartiteColor(child, g, colr, !paint);
}
} void maximumSoldier( int N, vector<vector< int > > arr)
{ // Creating a graph
// taking 20001 as the upper bound
// for unique soldiers.
vector<vector< int > > g(20001);
// set to store all the unique soldiers
set< int > st;
for ( int i = 0; i < N; i++) {
// u and v stores the soldier
int u, v;
u = arr[i][0];
v = arr[i][1];
// Initializing the graph
g[u].push_back(v);
g[v].push_back(u);
// Inserting u and v into set
st.insert(u);
st.insert(v);
}
// To store all the unique
// soldiers of set st
vector< int > soldiers;
for ( auto e : st)
soldiers.push_back(e);
// Initializing the result as ans=0
int ans = 0;
// colr[] to apply Bipartite coloring
vector< int > colr(20001, -1);
// Loop for each soldier
for ( auto e : soldiers) {
// if already colored we continue;
if (colr[e] != -1)
continue ;
// one and zero are our two colors.
one = 0;
zero = 0;
// Applying Bipartite Coloring
BipartiteColor(e, g, colr, 0);
// Updating our answer
ans += max(one, zero);
}
if (flag)
cout << ans;
else
cout << -1;
} // Driver Code int main()
{ // Input test case
int N = 4;
vector<vector< int > > arr
= { { 1, 2 }, { 2, 3 }, { 2, 4 }, { 2, 5 } };
// Function call
maximumSoldier(N, arr);
return 0;
} |
//Java code for the above approach import java.util.*;
public class GFG {
// one and zero are our two colors
static int one, zero;
// Flag to check whether the answer
// exists or not
static boolean flag = true ;
static void BipartiteColor( int v, List<List<Integer>> g,
List<Integer> colr, int paint) {
// if the vertex is already colored
if (colr.get(v) != - 1 ) {
// if previous color and current paint
// contradict each other then our answer
// won't exist
if (colr.get(v) != paint)
flag = false ;
return ;
}
// paint the current vertex v
colr.set(v, paint);
// if paint is 1
if (paint == 1 )
one++;
// if paint is 0
else
zero++;
// Recursive calls on the child of vertex v
for ( int child : g.get(v)) {
// Giving the complementary color to the
// child i.e. if colr[v]=1 then
// colr[child]=0 and vice versa
BipartiteColor(child, g, colr, (paint == 1 ) ? 0 : 1 );
}
}
static void maximumSoldier( int N, List<List<Integer>> arr) {
// Creating a graph
// taking 20001 as the upper bound
// for unique soldiers.
List<List<Integer>> g = new ArrayList<>();
for ( int i = 0 ; i < 20001 ; i++) {
g.add( new ArrayList<>());
}
// set to store all the unique soldiers
Set<Integer> st = new HashSet<>();
for ( int i = 0 ; i < N; i++) {
// u and v stores the soldier
int u, v;
u = arr.get(i).get( 0 );
v = arr.get(i).get( 1 );
// Initializing the graph
g.get(u).add(v);
g.get(v).add(u);
// Inserting u and v into set
st.add(u);
st.add(v);
}
// To store all the unique
// soldiers of set st
List<Integer> soldiers = new ArrayList<>(st);
// Initializing the result as ans=0
int ans = 0 ;
// colr[] to apply Bipartite coloring
List<Integer> colr = new ArrayList<>(Collections.nCopies( 20001 , - 1 ));
// Loop for each soldier
for ( int e : soldiers) {
// if already colored we continue;
if (colr.get(e) != - 1 )
continue ;
// one and zero are our two colors.
one = 0 ;
zero = 0 ;
// Applying Bipartite Coloring
BipartiteColor(e, g, colr, 0 );
// Updating our answer
ans += Math.max(one, zero);
}
if (flag)
System.out.println(ans);
else
System.out.println(- 1 );
}
// Driver Code
public static void main(String[] args) {
// Input test case
int N = 4 ;
List<List<Integer>> arr = new ArrayList<>();
arr.add(Arrays.asList( 1 , 2 ));
arr.add(Arrays.asList( 2 , 3 ));
arr.add(Arrays.asList( 2 , 4 ));
arr.add(Arrays.asList( 2 , 5 ));
// Function call
maximumSoldier(N, arr);
}
} |
# Python code for the above approach : # Function to perform Bipartite Coloring def bipartite_color(v, g, colr, paint):
global one, zero, flag
# If the vertex is already colored
if colr[v] ! = - 1 :
# If the previous color and current paint
# contradict each other, then our answer
# won't exist
if colr[v] ! = paint:
flag = False
return
# Paint the current vertex v
colr[v] = paint
# If paint is 1
if paint:
one + = 1
# If paint is 0
else :
zero + = 1
# Recursive calls on the child of vertex v
for child in g[v]:
# Giving the complementary color to the
# child, i.e., if colr[v]=1 then
# colr[child]=0 and vice versa
bipartite_color(child, g, colr, not paint)
# Function to find the maximum number of soldiers def maximum_soldier(N, arr):
global one, zero, flag
# Creating a graph with an upper bound of 20001
g = [[] for _ in range ( 20001 )]
# Set to store all the unique soldiers
st = set ()
for i in range (N):
# u and v store the soldier
u, v = arr[i][ 0 ], arr[i][ 1 ]
# Initializing the graph
g[u].append(v)
g[v].append(u)
# Inserting u and v into the set
st.add(u)
st.add(v)
# To store all the unique soldiers from the set
soldiers = list (st)
# Initializing the result as ans=0
ans = 0
# colr[] to apply Bipartite coloring
colr = [ - 1 ] * 20001
# Loop for each soldier
for e in soldiers:
# If already colored, continue
if colr[e] ! = - 1 :
continue
# one and zero are our two colors
one = 0
zero = 0
# Applying Bipartite Coloring
bipartite_color(e, g, colr, 0 )
# Updating our answer
ans + = max (one, zero)
if flag:
print (ans)
else :
print ( - 1 )
if __name__ = = "__main__" :
# Input test case
N = 4
arr = [[ 1 , 2 ], [ 2 , 3 ], [ 2 , 4 ], [ 2 , 5 ]]
flag = True
# Function call
maximum_soldier(N, arr)
# this code is contributed by uttamdp_10
|
//Java code for the above approach using System;
using System.Collections.Generic;
using System.Linq;
class GFG
{ // one and zero are our two colors
static int one, zero;
// Flag to check whether the answer
// exists or not
static bool flag = true ;
static void BipartiteColor( int v, List<List< int >> g, List< int > colr, int paint)
{
// If the vertex is already colored
if (colr[v] != -1)
{
// If previous color and current paint
// contradict each other then our answer
// won't exist
if (colr[v] != paint)
flag = false ;
return ;
}
// Paint the current vertex v
colr[v] = paint;
// If paint is 1
if (paint == 1)
one++;
// If paint is 0
else
zero++;
// Recursive calls on the child of vertex v
foreach ( int child in g[v])
{
// Giving the complementary color to the
// child, i.e. if colr[v] = 1 then
// colr[child] = 0 and vice versa
BipartiteColor(child, g, colr, (paint == 1) ? 0 : 1);
}
}
static void MaximumSoldier( int N, List<List< int >> arr)
{
// Creating a graph
// taking 20001 as the upper bound
// for unique soldiers.
List<List< int >> g = new List<List< int >>();
for ( int i = 0; i < 20001; i++)
{
g.Add( new List< int >());
}
// Set to store all the unique soldiers
HashSet< int > st = new HashSet< int >();
for ( int i = 0; i < N; i++)
{
// u and v stores the soldier
int u, v;
u = arr[i][0];
v = arr[i][1];
// Initializing the graph
g[u].Add(v);
g[v].Add(u);
// Inserting u and v into set
st.Add(u);
st.Add(v);
}
// To store all the unique
// soldiers of set st
List< int > soldiers = st.ToList();
// Initializing the result as ans = 0
int ans = 0;
// colr[] to apply Bipartite coloring
List< int > colr = Enumerable.Repeat(-1, 20001).ToList();
// Loop for each soldier
foreach ( int e in soldiers)
{
// if already colored we continue;
if (colr[e] != -1)
continue ;
// one and zero are our two colors.
one = 0;
zero = 0;
// Applying Bipartite Coloring
BipartiteColor(e, g, colr, 0);
// Updating our answer
ans += Math.Max(one, zero);
}
if (flag)
Console.WriteLine(ans);
else
Console.WriteLine(-1);
}
// Driver Code
public static void Main( string [] args)
{
// Input test case
int N = 4;
List<List< int >> arr = new List<List< int >>
{
new List< int > { 1, 2 },
new List< int > { 2, 3 },
new List< int > { 2, 4 },
new List< int > { 2, 5 }
};
// Function call
MaximumSoldier(N, arr);
}
} |
// Bipartite graph coloring variables let one, zero; let flag = true ;
function bipartiteColor(v, g, colr, paint) {
// If the vertex is already colored
if (colr[v] !== -1) {
// If previous color and current paint contradict each other
// then our answer won't exist
if (colr[v] !== paint) {
flag = false ;
}
return ;
}
colr[v] = paint;
if (paint === 1) {
one++;
} else {
zero++;
}
for (const child of g[v]) {
// Giving the complementary color to the child
// If colr[v] = 1, then colr[child] = 0 and vice versa
bipartiteColor(child, g, colr, paint === 1 ? 0 : 1);
}
} function maximumSoldier(N, arr) {
// Creating a graph
const g = new Array(20001).fill( null ).map(() => []);
const st = new Set();
for (let i = 0; i < N; i++) {
// u and v store the soldiers
const u = arr[i][0];
const v = arr[i][1];
// Initializing the graph
g[u].push(v);
g[v].push(u);
// Inserting u and v into the set
st.add(u);
st.add(v);
}
// Convert the set to an array of unique soldiers
const soldiers = [...st];
// Initialize the result as ans = 0
let ans = 0;
// Array colr[] to apply Bipartite coloring
const colr = new Array(20001).fill(-1);
// Loop for each soldier
for (const e of soldiers) {
// If already colored, continue
if (colr[e] !== -1) {
continue ;
}
one = 0;
zero = 0;
// Applying Bipartite Coloring
bipartiteColor(e, g, colr, 0);
// Updating the answer
ans += Math.max(one, zero);
}
if (flag) {
console.log(ans);
} else {
console.log(-1);
}
} // Input test case const N = 4; const arr = [ [1, 2],
[2, 3],
[2, 4],
[2, 5]
]; // Function call maximumSoldier(N, arr); |
4
Time Complexity: O(N*logN + N*(V+E)), where N is the size of arr[], V is the unique number of soldiers(vertices) and E is the total edges in the graph.
Auxiliary Space: O(V), where V is the unique number of soldiers(vertices)