Given array A[] of size N representing graph with N nodes. There is an undirected edge between i and A[i] for 1 <= i <= N. The Task for this problem is to find the minimum and maximum number of connected components in the given graph if it is allowed to add an edge between any two nodes from N nodes as long as each node has a degree at most 2 in the graph.
Examples:
Input: A[] = {2, 1, 4, 3, 6, 5}
Output: 1 3
Explanation: maximum number of connected components will be 3. minimum number of connected components will be 1 since we can add edge between node pairs (2, 3) and (4, 5).

Input: A[] = {2, 3, 1, 5, 6, 4}
Output: 2 2
Explanation: maximum number of connected components will be 2 and minimum will be 2 as well since it is not possible to add edge between any two nodes.

Approach: To solve the problem follow the below observations:
Observations:
Depth-First-Search can be used to solve this problem by finding connected components.
- If any connected component is forming loop then every node of that connected component will have degree 2 (since maximum degree node can have is 2) so it is not possible to add edge between this connected component to any other connected component.
- Connected component which does not have loop will have nodes with degree less than 2 so we can add edge here with another connected component which is not forming loop. One more thing to observe is that all these connected components which does not have loop can be connected together forming single connected component thus minimizing number of connected components.
- Maximum number of connected components will not have any edge added
keeping counter for connected components with loop and without loop (let say X and Y) will be enough and the answer for maximum number of connected components will be X + Y and minimum number of connected components will be X + 1 if Y != 0 and X if Y == 0.
Below are the steps for the above approach:
- Create adjacency list for graph as adj[N + 1] and fill the adjacency table with N edges.
- Create two counters for counting with and without looped connected components as loopConnectedComponents = 0, withoutLoopConnectedComponents = 0.
- Create visited vis[N + 1] array for depth-first-search.
- Create flag = 0 which tells if current connected component during dfs call has loop or not.
- Iterate over all N nodes and call dfs function for node which is not visited yet.
- In dfs(V, parent) function mark node V visited by making vis[V] = 1
- Iterate over neighbours of V as U if it is not visited and it is not the parent node of V then call dfs function for U
- else if U is not equal to parent and parent is not -1 then mark flag as 1.
- if flag is 1 then increment in loopConnectedComponents by 1 else increment withoutLoopConnectedComponents by 1.
- Create variable as maxConnectedComponents = loopConnectedComponents + withoutLoopConnectedComponents.
- Create variable as minConnectedComponents = loopConnectedComponents and increament it by 1 if withoutLoopConnectedComponents is non zero (since we will unify all connected components without loop into one).
- print minConnectedComponents and maxConnectedComponents.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool dfs( int V, int parent, int & flag, vector< int >& vis,
vector<vector< int > >& adj)
{
vis[V] = 1;
for ( auto & U : adj[V]) {
if (!vis[U]) {
dfs(U, V, flag, vis, adj);
}
else if (U != parent and parent != -1) {
flag = 1;
}
}
}
void findMinMaxCC( int A[], int N)
{
vector<vector< int > > adj(N + 1);
for ( int i = 0; i < N; i++) {
adj[i + 1].push_back(A[i]);
adj[A[i]].push_back(i + 1);
}
int loopConnectedComponents = 0,
withoutLoopConnectedComponents = 0;
vector< int > vis(N + 1, 0);
int flag = 0;
for ( int i = 1; i <= N; i++) {
if (!vis[i]) {
dfs(i, -1, flag, vis, adj);
if (flag)
loopConnectedComponents++;
else
withoutLoopConnectedComponents++;
flag = 0;
}
}
int maxConnectedComponents
= loopConnectedComponents
+ withoutLoopConnectedComponents;
int minConnectedComponents = loopConnectedComponents;
if (withoutLoopConnectedComponents != 0)
minConnectedComponents++;
cout << minConnectedComponents << " "
<< maxConnectedComponents << endl;
}
int32_t main()
{
int A[] = { 2, 1, 4, 3, 6, 5 }, N = 6;
findMinMaxCC(A, N);
int A1[] = { 2, 3, 1, 5, 6, 4 }, N1 = 6;
findMinMaxCC(A1, N1);
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.Arrays;
public class ConnectedComponents {
static void dfs( int V, int parent, int [] flag, int [] vis, ArrayList<ArrayList<Integer>> adj) {
vis[V] = 1 ;
for ( int U : adj.get(V)) {
if (vis[U] == 0 ) {
dfs(U, V, flag, vis, adj);
}
else if (U != parent && parent != - 1 ) {
flag[ 0 ] = 1 ;
}
}
}
static void findMinMaxCC( int [] A, int N) {
ArrayList<ArrayList<Integer>> adj = new ArrayList<>(N + 1 );
for ( int i = 0 ; i <= N; i++) {
adj.add( new ArrayList<>());
}
for ( int i = 0 ; i < N; i++) {
adj.get(i + 1 ).add(A[i]);
adj.get(A[i]).add(i + 1 );
}
int [] loopConnectedComponents = { 0 };
int [] withoutLoopConnectedComponents = { 0 };
int [] vis = new int [N + 1 ];
int [] flag = { 0 };
for ( int i = 1 ; i <= N; i++) {
if (vis[i] == 0 ) {
dfs(i, - 1 , flag, vis, adj);
if (flag[ 0 ] == 1 ) {
loopConnectedComponents[ 0 ]++;
}
else {
withoutLoopConnectedComponents[ 0 ]++;
}
flag[ 0 ] = 0 ;
}
}
int maxConnectedComponents = loopConnectedComponents[ 0 ] + withoutLoopConnectedComponents[ 0 ];
int minConnectedComponents = loopConnectedComponents[ 0 ];
if (withoutLoopConnectedComponents[ 0 ] != 0 ) {
minConnectedComponents++;
}
System.out.println(minConnectedComponents + " " + maxConnectedComponents);
}
public static void main(String[] args) {
int [] A = { 2 , 1 , 4 , 3 , 6 , 5 };
int N = 6 ;
findMinMaxCC(A, N);
int [] A1 = { 2 , 3 , 1 , 5 , 6 , 4 };
int N1 = 6 ;
findMinMaxCC(A1, N1);
}
}
|
Python
def dfs(V, parent, flag, vis, adj):
vis[V] = 1
for U in adj[V]:
if not vis[U]:
dfs(U, V, flag, vis, adj)
elif U ! = parent and parent ! = - 1 :
flag[ 0 ] = 1
def findMinMaxCC(A, N):
adj = [[] for _ in range (N + 1 )]
for i in range (N):
adj[i + 1 ].append(A[i])
adj[A[i]].append(i + 1 )
loopConnectedComponents = 0
withoutLoopConnectedComponents = 0
vis = [ 0 ] * (N + 1 )
flag = [ 0 ]
for i in range ( 1 , N + 1 ):
if not vis[i]:
dfs(i, - 1 , flag, vis, adj)
if flag[ 0 ]:
loopConnectedComponents + = 1
else :
withoutLoopConnectedComponents + = 1
flag[ 0 ] = 0
maxConnectedComponents = (
loopConnectedComponents + withoutLoopConnectedComponents
)
minConnectedComponents = loopConnectedComponents
if withoutLoopConnectedComponents ! = 0 :
minConnectedComponents + = 1
print (minConnectedComponents, maxConnectedComponents)
if __name__ = = "__main__" :
A = [ 2 , 1 , 4 , 3 , 6 , 5 ]
N = 6
findMinMaxCC(A, N)
A1 = [ 2 , 3 , 1 , 5 , 6 , 4 ]
N1 = 6
findMinMaxCC(A1, N1)
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static void DFS( int V, int parent, ref int flag,
List< int > vis, List<List< int > > adj)
{
vis[V] = 1;
foreach ( int U in adj[V])
{
if (vis[U] == 0) {
DFS(U, V, ref flag, vis, adj);
}
else if (U != parent && parent != -1) {
flag = 1;
}
}
}
static void FindMinMaxCC( int [] A, int N)
{
List<List< int > > adj = new List<List< int > >();
for ( int i = 0; i <= N; i++) {
adj.Add( new List< int >());
}
for ( int i = 0; i < N; i++) {
adj[i + 1].Add(A[i]);
adj[A[i]].Add(i + 1);
}
int loopConnectedComponents = 0;
int withoutLoopConnectedComponents = 0;
List< int > vis = new List< int >();
for ( int i = 0; i <= N; i++) {
vis.Add(0);
}
int flag = 0;
for ( int i = 1; i <= N; i++) {
if (vis[i] == 0) {
DFS(i, -1, ref flag, vis, adj);
if (flag == 1) {
loopConnectedComponents++;
}
else {
withoutLoopConnectedComponents++;
}
flag = 0;
}
}
int maxConnectedComponents
= loopConnectedComponents
+ withoutLoopConnectedComponents;
int minConnectedComponents
= loopConnectedComponents;
if (withoutLoopConnectedComponents != 0) {
minConnectedComponents++;
}
Console.WriteLine(minConnectedComponents + " "
+ maxConnectedComponents);
}
public static void Main( string [] args)
{
int [] A = { 2, 1, 4, 3, 6, 5 };
int N = 6;
FindMinMaxCC(A, N);
int [] A1 = { 2, 3, 1, 5, 6, 4 };
int N1 = 6;
FindMinMaxCC(A1, N1);
}
}
|
Javascript
function dfs(V, parent, vis, adj, flag) {
vis[V] = true ;
for (const U of adj[V]) {
if (!vis[U]) {
dfs(U, V, vis, adj, flag);
}
else if (U !== parent && parent !== -1) {
flag.flag = true ;
}
}
}
function GFG(A, N) {
const adj = new Array(N + 1).fill( null ).map(() => []);
for (let i = 0; i < N; i++) {
adj[i + 1].push(A[i]);
adj[A[i]].push(i + 1);
}
let loopConnectedComponents = 0;
let withoutLoopConnectedComponents = 0;
const vis = new Array(N + 1).fill( false );
const flag = { flag: false };
for (let i = 1; i <= N; i++) {
if (!vis[i]) {
dfs(i, -1, vis, adj, flag);
if (flag.flag) {
loopConnectedComponents++;
}
else {
withoutLoopConnectedComponents++;
}
flag.flag = false ;
}
}
const maxConnectedComponents =
loopConnectedComponents + withoutLoopConnectedComponents;
let minConnectedComponents = loopConnectedComponents;
if (withoutLoopConnectedComponents !== 0) {
minConnectedComponents++;
}
console.log(minConnectedComponents, maxConnectedComponents);
}
( function () {
const A = [2, 1, 4, 3, 6, 5];
const N = 6;
GFG(A, N);
const A1 = [2, 3, 1, 5, 6, 4];
const N1 = 6;
GFG(A1, N1);
})();
|
Time Complexity: O(N) Auxiliary Space: O(N)
|