Delete Maximum edges such that Graph is traversable
Last Updated : 23 Jul, 2025
Given an undirected graph of N node, where nodes are numbered from 1 to N, and an array of edges, where edges[i] = {edgeType, u, v} and two persons A and B are moving in it. Each edge type indicates different things.
edgeType = 0 indicates that only A can travel on that edge from node u to v.
edgeType = 1 indicates that only B can travel on that edge from node u to v.
edgeType = 2, then both persons can travel on that edge.
The task is to delete the maximum number of edges such that both persons still travel on all the nodes starting from any node or return -1 if both persons cannot fully traverse the graph.
Examples:
Input: N = 4, edges = { { 0, 1, 2 }, {0, 3, 4}, {1, 1, 2}, {1, 2, 4}, { 2, 1, 2 }, { 2, 1, 3 } } Output: 2 Explanation: Remove an edge between node 1 and node 2 which have edgeType = 0 Remove an edge between node 1 and node 2 which have edgeType = 1 The final node remaining is traversable by both the person.
Sort the edges[] on the basis of edgeType which is traversable by both. Use DSU for keeping track of number of connected component for both the person individually and initially assign count of connected component to N as we'll assume every node an individual component.
Try to connect edges which are traversable in their DSU, if edges are not redundant then add that edge and reduce the number of connected component by 1 for that person. Otherwise, remove that edge.
Finally check if any one have number of connected component greater than 1, means that person can't traverse every node. So, return -1. Otherwise, return count of remove.
Follow the steps below to implement the above idea:
Sort on the basis of that edge which is traversable by both person
Initialize a parentA[] for person A, parentB[] for person B
Initialize a rankA[] for person A, rankB[] for person B
Initially, every node is its own parent and make its rank = 1.
Create variable connectedComponentA and connectedComponentB to count the number of connected components where A and B can travel respectively.
Create a remove variable to keep track of how many redundant nodes can be removed.
Iterate over all the edges:
Connect that node with edges first which is traversable by both, (i.e, edgeType = 2)
Try to merge node into DSU for person A.
Try to merge node into DSU for person B.
If there is a merge of nodes in DSU for person A.
Decrement connectedComponentA by 1.
If there is a merge of nodes in DSU for person B.
Decrement connectedComponentB by 1.
If there is no merge of nodes in both the DSU
This edge is redundant. So, increment remove.
For edges with edgeType=0, try to merge node into DSU for person A
If there is a merge of nodes in DSU for person A.
Decrement connectedComponentA by 1.
If there is no merge of nodes in person A's DSU.
This edge is redundant. So, increment remove.
For edges with edgeType = 1, try to merge node into DSU for person B
If there is a merge of nodes in DSU for person B.
Decrement of connectedComponentB by 1
If there is no merge of nodes in person B's DSU
This edge is redundant. So, increment remove.
Finally, check if anyone's connected Component is not 1:
Then, there is no way to travel on all the nodes by both people. So, return -1
Otherwise, return the remove count.
Below is the implementation of the above approach.
C++
// C++ code to implement the approach#include<bits/stdc++.h>usingnamespacestd;// Function to be used as comparator for sortingboolstaticcmp(vector<int>&a,vector<int>&b){returna[0]>b[0];}// Function to find the parent of a nodeintfind(intx,vector<int>&parent){if(parent[x]==x)returnx;returnparent[x]=find(parent[x],parent);}// Function to create union of two disjoint setsboolunion1(intx,inty,vector<int>&parent,vector<int>&rank){intlx=find(x,parent);intly=find(y,parent);// Merge their leaderif(lx!=ly){if(rank[lx]>rank[ly]){parent[ly]=lx;}elseif(rank[lx]<rank[ly]){parent[lx]=ly;}else{parent[lx]=ly;rank[ly]+=1;}returntrue;}returnfalse;}// Function to find the maximum number// of edges that can be deletedintremoveMaxEdges(intn,vector<vector<int>>&edges){intn1=n+1;// Sort on the basis on that edge// which is traversable by both personsort(edges.begin(),edges.end(),cmp);// Initialize a parentA[] for person A,// parentB[] for person B Initialize a// rankA[] for person A, rankB[]// for person Bvector<int>parentA(n1),parentB(n1),rankA(n1),rankB(n1);// Initially every node as leader and// make their rank = 1.for(inti=1;i<=n;i++){parentA[i]=i;parentB[i]=i;rankA[i]=1;rankB[i]=1;}// Create variable connectedComponentA// to count number of connected// component where A can travel Create// variable connectedComponentB to// count number of connected component// where B can travel Create a remove// variable to keep track of how many// redundant node that need to remove.intconnectedComponentA=n,connectedComponentB=n,remove=0;// Iterate over all the edges.for(autoi:edges){// Connect the node with edges// first which is traversable// by bothif(i[0]==2){// Try to merge node into DSU// for person AboolmergeA=union1(i[1],i[2],parentA,rankA);// Try to merge node into DSU// for person BboolmergeB=union1(i[1],i[2],parentB,rankB);// If there is merge of nodes// in DSU for person A. then,// decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in both the DSU's then,// this edge is redundant. So,// increment remove.if(mergeA==false&&mergeB==false){remove++;}}elseif(i[0]==1){// Try to merge node into DSU// for person AboolmergeA=union1(i[1],i[2],parentA,rankA);// If there is merge of nodes// in DSU for person A.// then, decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is no merge of// nodes in person A's DSU then,// this edge is redundant. So,// increment remove.if(mergeA==false){remove++;}}else{// Try to merge node into DSU// for person BboolmergeB=union1(i[1],i[2],parentB,rankB);// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in person B's DSU// then, this edge is redundant.// So, increment remove.if(mergeB==false){remove++;}}}// Finally check if if any one's// connected Component is not 1,// then, there is no way to travel on// all the node by both person.// So, return -1if(connectedComponentA!=1||connectedComponentB!=1){return-1;}// Otherwise, return remove count.returnremove;}// Driver codeintmain(){intN=4;vector<vector<int>>edges={{0,1,2},{0,3,4},{1,1,2},{1,2,4},{2,1,2},{2,1,3}};// Function Callcout<<removeMaxEdges(N,edges);return0;}
Java
/*package whatever //do not write package name here */// java code additionimportjava.io.*;importjava.util.*;classGFG{// Function to find the parent of a nodepublicstaticintfind(intx,List<Integer>parent){if(parent.get(x)==x)returnx;parent.set(x,find(parent.get(x),parent));returnparent.get(x);}// Function to create union of two disjoint setspublicstaticbooleanunion1(intx,inty,List<Integer>parent,List<Integer>rank){intlx=find(x,parent);intly=find(y,parent);// Merge their leaderif(lx!=ly){if(rank.get(lx)>rank.get(ly)){parent.set(ly,lx);}elseif(rank.get(lx)<rank.get(ly)){parent.set(lx,ly);}else{parent.set(lx,ly);rank.set(ly,rank.get(ly)+1);}returntrue;}returnfalse;}// Function to find the maximum number// of edges that can be deletedpublicstaticintremoveMaxEdges(intn,List<List<Integer>>edges){intn1=n+1;// Sort on the basis on that edge// which is traversable by both personCollections.sort(edges,newComparator<List<Integer>>(){@Overridepublicintcompare(finalList<Integer>a,List<Integer>b){if(a.get(0)>b.get(0))return-1;return1;}});// Initialize a parentA[] for person A,// parentB[] for person B Initialize a// rankA[] for person A, rankB[]// for person BList<Integer>parentA=newArrayList<Integer>();List<Integer>parentB=newArrayList<Integer>();List<Integer>rankA=newArrayList<Integer>();List<Integer>rankB=newArrayList<Integer>();for(inti=1;i<=n1;i++){parentA.add(0);parentB.add(0);rankA.add(0);rankB.add(0);}// Initially every node as leader and// make their rank = 1.for(inti=1;i<=n;i++){parentA.set(i,i);parentB.set(i,i);rankA.set(i,1);rankB.set(i,1);}// Create variable connectedComponentA// to count number of connected// component where A can travel Create// variable connectedComponentB to// count number of connected component// where B can travel Create a remove// variable to keep track of how many// redundant node that need to remove.intconnectedComponentA=n,connectedComponentB=n,remove=0;// Iterate over all the edges.for(intj=0;j<edges.size();j++){List<Integer>i=edges.get(j);// Connect the node with edges// first which is traversable// by bothif(i.get(0)==2){// Try to merge node into DSU// for person AbooleanmergeA=union1(i.get(1),i.get(2),parentA,rankA);// Try to merge node into DSU// for person BbooleanmergeB=union1(i.get(1),i.get(2),parentB,rankB);// If there is merge of nodes// in DSU for person A. then,// decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in both the DSU's then,// this edge is redundant. So,// increment remove.if(mergeA==false&&mergeB==false){remove++;}}elseif(i.get(0)==1){// Try to merge node into DSU// for person AbooleanmergeA=union1(i.get(1),i.get(2),parentA,rankA);// If there is merge of nodes// in DSU for person A.// then, decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is no merge of// nodes in person A's DSU then,// this edge is redundant. So,// increment remove.if(mergeA==false){remove++;}}else{// Try to merge node into DSU// for person BbooleanmergeB=union1(i.get(1),i.get(2),parentB,rankB);// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in person B's DSU// then, this edge is redundant.// So, increment remove.if(mergeB==false){remove++;}}}// Finally check if if any one's// connected Component is not 1,// then, there is no way to travel on// all the node by both person.// So, return -1if(connectedComponentA!=1||connectedComponentB!=1){return-1;}// Otherwise, return remove count.returnremove;}publicstaticvoidmain(String[]args){intN=4;List<List<Integer>>edges=newArrayList<List<Integer>>();List<Integer>a=newArrayList<Integer>();a.add(0);a.add(1);a.add(2);edges.add(a);List<Integer>b=newArrayList<Integer>();b.add(0);b.add(3);b.add(4);edges.add(b);List<Integer>c=newArrayList<Integer>();c.add(1);c.add(1);c.add(2);edges.add(c);List<Integer>d=newArrayList<Integer>();d.add(1);d.add(2);d.add(4);edges.add(d);List<Integer>e=newArrayList<Integer>();e.add(2);e.add(1);e.add(2);edges.add(e);List<Integer>f=newArrayList<Integer>();f.add(2);f.add(1);f.add(3);edges.add(f);// Function CallSystem.out.println(removeMaxEdges(N,edges));}}// This code is contributed by ksam24000.
C#
// C# implementationusingSystem;usingSystem.Collections;usingSystem.Collections.Generic;publicclassGFG{// Function to be used as comparator for sortingpublicstaticintcmp(List<int>a,List<int>b){if(a[0]>b[0])return-1;return1;}// Function to find the parent of a nodepublicstaticintfind(intx,List<int>parent){if(parent[x]==x)returnx;returnparent[x]=find(parent[x],parent);}// Function to create union of two disjoint setspublicstaticboolunion1(intx,inty,List<int>parent,List<int>rank){intlx=find(x,parent);intly=find(y,parent);// Merge their leaderif(lx!=ly){if(rank[lx]>rank[ly]){parent[ly]=lx;}elseif(rank[lx]<rank[ly]){parent[lx]=ly;}else{parent[lx]=ly;rank[ly]+=1;}returntrue;}returnfalse;}// Function to find the maximum number// of edges that can be deletedpublicstaticintremoveMaxEdges(intn,List<List<int>>edges){intn1=n+1;// Sort on the basis on that edge// which is traversable by both personedges.Sort(cmp);// Initialize a parentA[] for person A,// parentB[] for person B Initialize a// rankA[] for person A, rankB[]// for person BList<int>parentA=newList<int>();List<int>parentB=newList<int>();List<int>rankA=newList<int>();List<int>rankB=newList<int>();for(inti=0;i<n1;i++){parentA.Add(0);parentB.Add(0);rankA.Add(0);rankB.Add(0);}// Initially every node as leader and// make their rank = 1.for(inti=1;i<=n;i++){parentA[i]=i;parentB[i]=i;rankA[i]=1;rankB[i]=1;}// Create variable connectedComponentA// to count number of connected// component where A can travel Create// variable connectedComponentB to// count number of connected component// where B can travel Create a remove// variable to keep track of how many// redundant node that need to remove.intconnectedComponentA=n,connectedComponentB=n,remove=0;// Iterate over all the edges.for(inti=0;i<edges.Count;i++){// Connect the node with edges// first which is traversable// by bothif(edges[i][0]==2){// Try to merge node into DSU// for person AboolmergeA=union1(edges[i][1],edges[i][2],parentA,rankA);// Try to merge node into DSU// for person BboolmergeB=union1(edges[i][1],edges[i][2],parentB,rankB);// If there is merge of nodes// in DSU for person A. then,// decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in both the DSU's then,// this edge is redundant. So,// increment remove.if(mergeA==false&&mergeB==false){remove++;}}elseif(edges[i][0]==1){// Try to merge node into DSU// for person AboolmergeA=union1(edges[i][1],edges[i][2],parentA,rankA);// If there is merge of nodes// in DSU for person A.// then, decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is no merge of// nodes in person A's DSU then,// this edge is redundant. So,// increment remove.if(mergeA==false){remove++;}}else{// Try to merge node into DSU// for person BboolmergeB=union1(edges[i][1],edges[i][2],parentB,rankB);// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in person B's DSU// then, this edge is redundant.// So, increment remove.if(mergeB==false){remove++;}}}// Finally check if if any one's// connected Component is not 1,// then, there is no way to travel on// all the node by both person.// So, return -1if(connectedComponentA!=1||connectedComponentB!=1){return-1;}// Otherwise, return remove count.returnremove;}// Driver codestaticpublicvoidMain(){intN=4;List<List<int>>edges=newList<List<int>>{newList<int>{0,1,2},newList<int>{0,3,4},newList<int>{1,1,2},newList<int>{1,2,4},newList<int>{2,1,2},newList<int>{2,1,3}};// Function CallConsole.WriteLine(removeMaxEdges(N,edges));}}// This code is contributed by ksam24000
JavaScript
// JavaScript code for the above approach// Function to find the parent of a nodefunctionfind(x,parent){if(parent[x]==x)returnx;returnparent[x]=find(parent[x],parent);}// Function to create union of two disjoint setsfunctionunion1(x,y,parent,rank){letlx=find(x,parent);letly=find(y,parent);// Merge their leaderif(lx!=ly){if(rank[lx]>rank[ly]){parent[ly]=lx;}elseif(rank[lx]<rank[ly]){parent[lx]=ly;}else{parent[lx]=ly;rank[ly]+=1;}returntrue;}returnfalse;}// Function to find the maximum number// of edges that can be deletedfunctionremoveMaxEdges(n,edges){letn1=n+1;// Sort on the basis on that edge// which is traversable by both personedges.sort(function(a,b){returnb[0]-a[0]});// Initialize a parentA[] for person A,// parentB[] for person B Initialize a// rankA[] for person A, rankB[]// for person BletparentA=newArray(n1),parentB=newArray(n1),rankA=newArray(n1);rankB=newArray(n1);// Initially every node as leader and// make their rank = 1.for(leti=1;i<=n;i++){parentA[i]=i;parentB[i]=i;rankA[i]=1;rankB[i]=1;}// Create variable connectedComponentA// to count number of connected// component where A can travel Create// variable connectedComponentB to// count number of connected component// where B can travel Create a remove// variable to keep track of how many// redundant node that need to remove.letconnectedComponentA=n,connectedComponentB=n,remove=0;// Iterate over all the edges.for(letiofedges){// Connect the node with edges// first which is traversable// by bothif(i[0]==2){// Try to merge node into DSU// for person AletmergeA=union1(i[1],i[2],parentA,rankA);// Try to merge node into DSU// for person BletmergeB=union1(i[1],i[2],parentB,rankB);// If there is merge of nodes// in DSU for person A. then,// decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in both the DSU's then,// this edge is redundant. So,// increment remove.if(mergeA==false&&mergeB==false){remove++;}}elseif(i[0]==1){// Try to merge node into DSU// for person AletmergeA=union1(i[1],i[2],parentA,rankA);// If there is merge of nodes// in DSU for person A.// then, decrement of// connectedComponentA by 1if(mergeA){connectedComponentA--;}// If there is no merge of// nodes in person A's DSU then,// this edge is redundant. So,// increment remove.if(mergeA==false){remove++;}}else{// Try to merge node into DSU// for person BletmergeB=union1(i[1],i[2],parentB,rankB);// If there is merge of nodes// in DSU for person B. then,// decrement of// connectedComponentB by 1if(mergeB){connectedComponentB--;}// If there is no merge of// nodes in person B's DSU// then, this edge is redundant.// So, increment remove.if(mergeB==false){remove++;}}}// Finally check if if any one's// connected Component is not 1,// then, there is no way to travel on// all the node by both person.// So, return -1if(connectedComponentA!=1||connectedComponentB!=1){return-1;}// Otherwise, return remove count.returnremove;}// Driver codeletN=4;letedges=[[0,1,2],[0,3,4],[1,1,2],[1,2,4],[2,1,2],[2,1,3]];// Function Callconsole.log(removeMaxEdges(N,edges));// This code is contributed by Potta Lokesh
Python3
fromfunctoolsimportcmp_to_keydefcmp(a,b):returna[0]>b[0]#Function to find the parent of a nodedeffind(x,parent):ifparent[x]==x:returnxparent[x]=find(parent[x],parent)returnparent[x]#Function to create union of two disjoint setsdefunion1(x,y,parent,rank):lx=find(x,parent)ly=find(y,parent)#Merge their leaderiflx!=ly:ifrank[lx]>rank[ly]:parent[ly]=lxelifrank[lx]<rank[ly]:parent[lx]=lyelse:parent[lx]=lyrank[ly]+=1returnTruereturnFalse#Function to find the maximum number of edges that can be deleteddefremoveMaxEdges(n,edges):n1=n+1# Sort on the basis on that edge# which is traversable by both personedges.sort(key=cmp_to_key(cmp))#Initialize a parentA[] for person A,# parentB[] for person B Initialize a# rankA[] for person A, rankB[]# for person BparentA,parentB=[0]*n1,[0]*n1rankA,rankB=[0]*n1,[0]*n1#Initially every node as leader and# make their rank = 1.foriinrange(1,n1):parentA[i]=iparentB[i]=irankA[i]=1rankB[i]=1#Create variable connectedComponentA# to count number of connected# component where A can travel Create# variable connectedComponentB to# count number of connected component# where B can travel Create a remove# variable to keep track of how many# redundant node that need to remove.connectedComponentA,connectedComponentB=n,nremove=1foriinedges:# Connect the node with edges# first which is traversable# by bothifi[0]==2:mergeA=union1(i[1],i[2],parentA,rankA)mergeB=union1(i[1],i[2],parentB,rankB)# Try to merge node into DSU# for person AifmergeA:connectedComponentA-=1# Try to merge node into DSU# for person BifmergeB:connectedComponentB-=1ifnotmergeAandnotmergeB:remove+=1elifi[0]==1:mergeA=union1(i[1],i[2],parentA,rankA)# If there is merge of nodes# in DSU for person A. then,# decrement of# connectedComponentA by 1ifmergeA:connectedComponentA-=1ifnotmergeA:remove+=1else:mergeB=union1(i[1],i[2],parentB,rankB)ifmergeB:connectedComponentB-=1ifnotmergeB:remove+=1# Finally check if if any one's# connected Component is not 1,# then, there is no way to travel on# all the node by both person.# So, return -1ifconnectedComponentA!=1orconnectedComponentB!=1:return-1returnremoveif__name__=='__main__':N=4edges=[[0,1,2],[0,3,4],[1,1,2],[1,2,4],[2,1,2],[2,1,3]]# Function Callprint(removeMaxEdges(N,edges))
Output
2
Time Complexity: O(E * log(N) + E), where E, and N are the number of edges and number of nodes respectively. Auxiliary Space: O(N)