# Minimize number of notes required to be distributed among students

• Difficulty Level : Basic
• Last Updated : 14 Sep, 2021

Given an array arr[] consisting of N strings representing the name of the students in the class and another array of pairs P[] such that P[i] likes P[i], the task is to find the minimum number of notes to be distributed in the class such that sharing of notes can take place only if a student likes another student either directly or indirectly.

Examples:

Input: arr[] = {geeks, for, code, run, compile}, P[][] = {{geeks, for}, {for, code}, {code, run}, {run, compile}, {run, for}}
Output: 3
Explanation:
Below is the image to represent the relationship among the students: From the above image:

1. Students named {“for”, “code”, “run”} require a single copy of notes, since there exists a mutual relationship between them.
2. Student named {“geeks”} requires a single copy of notes.
3. Student named {“compile”} also require a single copy of notes.

So, the minimum number of notes required is 3.

Input: arr[] = {geeks, for, all, run, debug, compile}, P[][] = {{geeks, for}, {for, all}, {all, geeks}, {for, run}, {run, compile}, {compile, debug}, {debug, run}}
Output: 2

Approach: The given problem can be solved by finding the number of strongly connected components in a directed graph after generating the relationship graph with the given conditions. Follow the steps below to solve the problem:

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach``#include ``using` `namespace` `std;` `// Structure of class Graph``class` `Graph {` `    ``// No. of vertices``    ``int` `V;` `    ``// An array of adjacency lists``    ``list<``int``>* adj;` `    ``// Function that fills the stack``    ``// with the vertices v``    ``void` `fillOrder(``int` `v, ``bool` `visited[],``                   ``stack<``int``>& Stack);` `    ``// Recursive function to perform``    ``// the DFS starting from v``    ``void` `DFSUtil(``int` `v, ``bool` `visited[]);` `public``:``    ``Graph(``int` `V);``    ``void` `addEdge(``int` `v, ``int` `w);` `    ``// Function to count the number of``    ``// strongly connected components``    ``void` `countSCCs();` `    ``// Function that returns reverse``    ``// (or transpose) of the graph``    ``Graph getTranspose();``};` `// Constructor of the Graph``Graph::Graph(``int` `V)``{``    ``this``->V = V;``    ``adj = ``new` `list<``int``>[V];``}` `// Recursive function to perform the``// DFS  starting from v``void` `Graph::DFSUtil(``int` `v, ``bool` `visited[])``{``    ``// Mark the current node as visited``    ``visited[v] = ``true``;` `    ``// Recurr for all the vertices``    ``// adjacent to this vertex``    ``list<``int``>::iterator i;` `    ``for` `(i = adj[v].begin();``         ``i != adj[v].end(); ++i) {``        ``if` `(!visited[*i])``            ``DFSUtil(*i, visited);``    ``}``}` `// Function to return the reverse``// (or transpose) of the graph``Graph Graph::getTranspose()``{``    ``Graph g(V);``    ``for` `(``int` `v = 0; v < V; v++) {` `        ``// Recurr for all the vertices``        ``// adjacent to this vertex``        ``list<``int``>::iterator i;` `        ``for` `(i = adj[v].begin();``             ``i != adj[v].end(); ++i) {``            ``g.adj[*i].push_back(v);``        ``}``    ``}``    ``return` `g;``}` `// Function to add an edge``void` `Graph::addEdge(``int` `v, ``int` `w)``{``    ``// Add w to v’s list``    ``adj[v].push_back(w);``}` `// Function to fill the stack with``// the vertices during DFS traversal``void` `Graph::fillOrder(``int` `v, ``bool` `visited[],``                      ``stack<``int``>& Stack)``{``    ``// Mark the current node as visited``    ``visited[v] = ``true``;` `    ``// Recurr for all the vertices``    ``// adjacent to this vertex``    ``list<``int``>::iterator i;` `    ``for` `(i = adj[v].begin();``         ``i != adj[v].end(); ++i) {``        ``if` `(!visited[*i])``            ``fillOrder(*i, visited, Stack);``    ``}` `    ``// All vertices reachable from``    ``// the node v are processed``    ``// Update the stack``    ``Stack.push(v);``}` `// Function that counts the strongly``// connected components in the graph``void` `Graph::countSCCs()``{``    ``stack<``int``> Stack;` `    ``// Mark all the vertices as not``    ``// visited (For first DFS)``    ``bool``* visited = ``new` `bool``[V];``    ``for` `(``int` `i = 0; i < V; i++)``        ``visited[i] = ``false``;` `    ``// Fill vertices in the stack``    ``// according to their finishing``    ``// time``    ``for` `(``int` `i = 0; i < V; i++) {``        ``// Vertex i is not visited``        ``if` `(visited[i] == ``false``)``            ``fillOrder(i, visited, Stack);``    ``}` `    ``// Create a reversed graph``    ``Graph gr = getTranspose();` `    ``// Mark all the vertices as``    ``// not visited (For second DFS)``    ``for` `(``int` `i = 0; i < V; i++)``        ``visited[i] = ``false``;``    ``int` `cnt = 0;` `    ``// Now process all vertices in``    ``// order defined by Stack``    ``while` `(Stack.empty() == ``false``) {` `        ``// Pop a vertex from stack``        ``int` `v = Stack.top();``        ``Stack.pop();` `        ``// Get the strongly connected``        ``// component of the popped``        ``// vertex``        ``if` `(visited[v] == ``false``) {` `            ``gr.DFSUtil(v, visited);``            ``cnt++;``        ``}``    ``}` `    ``// Print the result``    ``cout << cnt;``}` `// Function that counts the minimum``// number of notes required with the``// given criteria``void` `solve(vector& A,``           ``vector >& P)``{` `    ``Graph g(A.size());` `    ``// Used to map the strings to``    ``// their respective indices``    ``unordered_map um;``    ``for` `(``int` `i = 0; i < A.size(); i++) {``        ``um[A[i]] = i;``    ``}` `    ``// Iterate through all the edges``    ``// and add them to the graph``    ``for` `(``int` `i = 0; i < P.size(); i++) {``        ``int` `x = um[P[i]];``        ``int` `y = um[P[i]];``        ``g.addEdge(x, y);``    ``}` `    ``// Function Call``    ``g.countSCCs();``}` `// Driver Code``int` `main()``{` `    ``vector arr``        ``= { ``"geeks"``, ``"for"``, ``"code"``,``            ``"run"``, ``"compile"` `};``    ``vector > P = { { ``"geeks"``, ``"for"` `},``                                  ``{ ``"for"``, ``"code"` `},``                                  ``{ ``"code"``, ``"run"` `},``                                  ``{ ``"run"``, ``"compile"` `},``                                  ``{ ``"run"``, ``"for"` `} };` `    ``solve(arr, P);` `    ``return` `0;``}`

## Java

 `// Java program for above approach``import` `java.util.ArrayList;``import` `java.util.*;` `// Structure of class Graph``public` `class` `Graph{``    ` `// No. of vertices``int` `V;` `// An array of adjacency lists``ArrayList>  adj;` `// Constructor of the Graph``Graph(``int` `V)``{``    ``this``.V = V;``    ``adj = ``new` `ArrayList<>();``    ``for``(``int` `i = ``0``; i < V; i++)``    ``{``        ``adj.add(``new` `ArrayList<>());``    ``}``}` `// Recursive function to perform the``// DFS  starting from v``void` `DFSUtil(``int` `v, ``boolean` `visited[])``{``    ` `    ``// Mark the current node as visited``    ``visited[v] = ``true``;` `    ``// Recurr for all the vertices``    ``// adjacent to this vertex``    ``for``(``int` `i : adj.get(v))``    ``{``        ``if` `(!visited[i])``            ``DFSUtil(i, visited);``    ``}``}` `// Function to return the reverse``// (or transpose) of the graph``Graph getTranspose()``{``    ``Graph g = ``new` `Graph(V);``    ``for``(``int` `v = ``0``; v < V; v++)``    ``{``        ` `        ``// Recurr for all the vertices``        ``// adjacent to this vertex``        ``for``(``int` `i : adj.get(v))``        ``{``            ``g.adj.get(i).add(v);``        ``}``    ``}``    ``return` `g;``}` `// Function to add an edge``void` `addEdge(``int` `v, ``int` `w)``{``    ` `    ``// Add w to v’s list``    ``adj.get(v).add(w);``}` `// Function to fill the stack with``// the vertices during DFS traversal``void` `fillOrder(``int` `v, ``boolean``[] visited,``               ``Stack stack)``{``    ` `    ``// Mark the current node as visited``    ``visited[v] = ``true``;` `    ``// Recurr for all the vertices``    ``// adjacent to this vertex``    ``for``(``int` `i : adj.get(v))``    ``{``        ``if` `(!visited[i])``            ``fillOrder(i, visited, stack);``    ``}` `    ``// All vertices reachable from``    ``// the node v are processed``    ``// Update the stack``    ``stack.push(v);``}` `// Function that counts the strongly``// connected components in the graph``void` `countSCCs()``{``    ``Stack stack = ``new` `Stack<>();` `    ``// Mark all the vertices as not``    ``// visited (For first DFS)``    ``boolean``[] visited = ``new` `boolean``[V];``    ``for``(``int` `i = ``0``; i < V; i++)``        ``visited[i] = ``false``;` `    ``// Fill vertices in the stack``    ``// according to their finishing``    ``// time``    ``for``(``int` `i = ``0``; i < V; i++)``    ``{``        ` `        ``// Vertex i is not visited``        ``if` `(visited[i] == ``false``)``            ``fillOrder(i, visited, stack);``    ``}` `    ``// Create a reversed graph``    ``Graph gr = getTranspose();` `    ``// Mark all the vertices as``    ``// not visited (For second DFS)``    ``for``(``int` `i = ``0``; i < V; i++)``        ``visited[i] = ``false``;``        ` `    ``int` `cnt = ``0``;` `    ``// Now process all vertices in``    ``// order defined by Stack``    ``while` `(stack.empty() == ``false``)``    ``{``        ` `        ``// Pop a vertex from stack``        ``int` `v = stack.peek();``        ``stack.pop();` `        ``// Get the strongly connected``        ``// component of the popped``        ``// vertex``        ``if` `(visited[v] == ``false``)``        ``{``            ``gr.DFSUtil(v, visited);``            ``cnt++;``        ``}``    ``}` `    ``// Print the result``    ``System.out.print(cnt);``}` `// Function that counts the minimum``// number of notes required with the``// given criteria``static` `void` `solve(ArrayList A,``        ``ArrayList> P)``{``    ``Graph g = ``new` `Graph(A.size());` `    ``// Used to map the strings to``    ``// their respective indices``    ``HashMap um = ``new` `HashMap<>();``    ``for``(``int` `i = ``0``; i < A.size(); i++)``    ``{``        ``um.put(A.get(i), i);``    ``}` `    ``// Iterate through all the edges``    ``// and add them to the graph``    ``for``(``int` `i = ``0``; i < P.size(); i++)``    ``{``        ``int` `x = um.get(P.get(i).get(``0``));``        ``int` `y = um.get(P.get(i).get(``1``));``        ``g.addEdge(x, y);``    ``}` `    ``// Function Call``    ``g.countSCCs();``}` `// Driver code``public` `static` `void` `main(String[] args)``{``    ``ArrayList arr = ``new` `ArrayList<>();``    ``arr.add(``"geeks"``);``    ``arr.add(``"for"``);``    ``arr.add(``"code"``);``    ``arr.add(``"run"``);``    ``arr.add(``"compile"``);` `    ``ArrayList > P = ``new` `ArrayList<>();``    ``for``(``int` `i = ``0``; i < ``5``; i++)``        ``P.add(``new` `ArrayList<>());``        ` `    ``P.get(``0``).add(``"geeks"``);``    ``P.get(``0``).add(``"for"``);``    ``P.get(``1``).add(``"for"``);``    ``P.get(``1``).add(``"code"``);``    ``P.get(``2``).add(``"code"``);``    ``P.get(``2``).add(``"run"``);``    ``P.get(``3``).add(``"run"``);``    ``P.get(``3``).add(``"compile"``);``    ``P.get(``4``).add(``"run"``);``    ``P.get(``4``).add(``"for"``);` `    ``solve(arr, P);``}``}` `// This code is contributed by hritikrommie`

Output:

`3`

Time Complexity: O(N + M)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up