


The first line of input contains an integer T, the number of test cases.
The first line of each test case contains two single space-separated integers ‘V’, and ‘E’. ‘V’ represents the number of nodes and ‘E’ represents the number of edges in the graph.
From the second line onwards of each test case, the next 'E' lines will denote the edges of the graph where every edge is defined by two single space-separated integers 'A' and 'B', which signifies an edge from vertex 'A’ to vertex 'B'.
For each test case print "true" if a cycle exists, else "false".
1 <= T <= 10
1 <= V <= 10^3
0 <= E <= 10^3
0 <= A, B < V
Time Limit: 1sec
To change a directed tree to a cyclic directed graph by adding one edge, we can choose a node that has more than zero ancestors and add an edge from that node to one of its ancestors. This can always form a complete cycle. This edge is called the back edge.
The basic idea is to traverse a graph using DFS and keep track of visited nodes and search for the back edge. If we found any back edge, we will return true, else we will return false.
DFS for a connected graph produces a tree. There is a cycle in a graph only if there is a back edge present in the graph. A back edge is an edge that is from a node to itself (self-loop) or one of its ancestors in the tree produced by DFS.
To detect a back edge, we can use coloring to keep track of visited nodes as well as ancestors. The color “0” represents an unvisited node. All the nodes with the color “1” represent the ancestor of the node. The color “2” represents visited nodes that are not ancestors of the node. We can traverse the graph using DFS and for each node, we check if there is any back edge that connects to its ancestor with color “1”. If we find any back edge then return true otherwise return false.
For a disconnected graph, we run the same algorithm of each connected graph and return true if there is a back edge in any of the connected graphs.
Algorithm: