 GFG App
Open App Browser
Continue

# Check if a cycle exists between nodes S and T in an Undirected Graph with only S and T repeating | Set – 2

Given an undirected graph with N nodes and two vertices S & T, the task is to check if a cycle between these two vertices exists (and return it) or not, such that no other node except S and T appears more than once in that cycle.

Examples:

Input: N = 7, edges[][] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 2}, {2, 6}, {6, 0}}, S = 0, T = 4 Output: No simple cycle from S to T exists
Explanation: No simple cycle from S to T exists,
because node 2 appears two times, in the only cycle that exists between 0 & 4

Input: N = 7,  edges[][] = {{0, 1}, {1, 2}, {1, 6}, {2, 3}, {3, 4}, {4, 5}, {5, 2}, {2, 6}, {6, 0}},, S = 0, T = 4 Output:  0->1->3->4->5->2->6->0
Explanation: The cycle doesn’t repeat any node (except 0)

Naive approach: The naive approach of the problem is discussed in Set-1 of this problem.

Efficient Approach: In the naive approach there is checking for all possible paths. The idea in this approach is similar to the Ford Fulkerson algorithm with Edmonds-Karp implementation, but with only 2 BFS. Follow the below steps to solve the problem

1. First, make a directed graph by duplicating each node (except S and T) in receiver and sender:
• If the original graph had the edge: {a, b}, the new graph will have {sender_a, receiver_b}
• The only node that points to a sender is his receiver, so the only edge that ends in sender_v is: {receiver_v, sender_v}
2. Run a BFS to find a path from S to T, and memorize the path back (using a predecessor array).
3. Invert the edges in the path found, this step is similar to the update of an augmenting path in Ford Fulkerson.
• While inverting memorize the flow from one node to another in the path
• So, if the previous node of cur is pred, then flow[cur] = pred
• Finally, memorize the last node (before the node t), let’s call it: first_node (because it’s the first node, after t, of the flow_path), first_node = flow[t]
4. Run a BFS again to find the second path, and memorize the path back (using a predecessor array).
5. Memorize the flow of the second path again:
• Only mark the flow if there wasn’t a previous flow in an opposite direction, this way two opposite flows will be discarded. Therefore, if flow[pred] == cur don’t do: flow[cur] = pred
• If the previous node of cur is pred in a path, then flow[cur] = pred
6. Finally, join the paths:
• Traverse both paths by the flow, one path starting in first_node and the other flow[t]
• As we have 2 paths from t to s, by reverting one of them we will have one path from s to t and another from t to s.
• Traverse one path from s to t, and the other from t to s.

All this work duplicating the graph and registering the flow is done to assure that the same node won’t be traversed twice.

Below is the implementation of the above approach:

## Python3

 `# Python program for the above approach`   `# Auxiliary data struct for the BFS:` `class` `Node:` `    ``def` `__init__(``self``, val):` `        ``self``.val ``=` `val` `        ``self``.``next` `=` `None`     `class` `queue:` `    ``def` `__init__(``self``):` `        ``self``.head ``=` `None` `        ``self``.tail ``=` `None`   `    ``def` `empty(``self``):` `        ``return` `self``.head ``=``=` `None`   `    ``def` `push(``self``, val):` `        ``if` `self``.head ``is` `None``:` `            ``self``.head ``=` `Node(val)` `            ``self``.tail ``=` `self``.head` `        ``else``:` `            ``self``.tail.``next` `=` `Node(val)` `            ``self``.tail ``=` `self``.tail.``next`   `    ``def` `pop(``self``):` `        ``returned ``=` `self``.head.val` `        ``self``.head ``=` `self``.head.``next` `        ``return` `returned`     `# BFS to find the paths` `def` `bfs(graph, s, t):`   `    ``# Number of nodes in original graph` `    ``N ``=` `len``(graph)``/``/``2`   `    ``Q ``=` `queue()` `    ``Q.push(s)`   `    ``predecessor ``=` `list``(``-``1` `for` `_ ``in` `range``(``2` `*` `N))` `    ``predecessor[s] ``=` `s`   `    ``while` `not` `Q.empty():` `        ``cur ``=` `Q.pop()`   `        ``# Add neighbors to the queue` `        ``for` `neighbour ``in` `graph[cur]:`   `            ``# If we reach node we found the path` `            ``if` `neighbour ``=``=` `t ``or` `neighbour ``=``=` `t ``+` `N:` `                ``predecessor[t] ``=` `cur` `                ``predecessor[t ``+` `N] ``=` `cur` `                ``return` `predecessor` `            ``# Not seen` `            ``if` `predecessor[neighbour] ``=``=` `-``1``:` `                ``Q.push(neighbour)` `                ``predecessor[neighbour] ``=` `cur`   `    ``return` `None`   `# Invert the path and register flow`     `def` `invert_path(graph, predecessor, flow, s, t):` `    ``N ``=` `len``(graph)``/``/``2` `    ``cur ``=` `t`   `    ``while` `cur !``=` `s:` `        ``pred ``=` `predecessor[cur]`   `        ``if` `flow[pred] !``=` `cur:` `            ``flow[cur] ``=` `pred`   `        ``# Reverse edge` `        ``graph[cur].append(pred)` `        ``graph[pred].remove(cur)`   `        ``cur ``=` `pred`   `    ``# Node S and T are not duplicated` `    ``# so we don't reverse the edge s->(s + N)` `    ``# because it shouldn't exist` `    ``graph[s].append(s ``+` `N)`   `    ``return` `flow`   `# Return the path by the flow` `def` `flow_path(flow, first_node, s):` `    ``path ``=` `[]` `    ``cur ``=` `first_node` `    ``while` `cur !``=` `s:` `        ``path.append(cur)` `        ``cur ``=` `flow[cur]`   `    ``return` `path`   `# Function to get the cyclle with 2 nodes` `def` `cycleWith2Nodes(graph, s ``=` `0``, t ``=` `1``):` `    ``# Number of nodes in the graph` `    ``N ``=` `len``(graph)`   `    ``# Duplicate nodes:`   `    ``# Adjacency list of sender nodes` `    ``graph ``+``=` `list``(graph[node] ``for` `node ``in` `range``(N))`   `    ``# Adjacency list of receiver nodes` `    ``graph[:N] ``=` `list``([node ``+` `N] ``for` `node ``in` `range``(N))` `    ``# print('duplicated graph:', graph, '\n')`   `    ``# Find a path from s to t` `    ``predecessor ``=` `bfs(graph, s, t)` `    ``if` `predecessor ``is` `not` `None``:` `        ``# List to memorize the flow` `        ``# flow from node v is:` `        ``# flow[v], which gives the node who` `        ``# receives the flow` `        ``flow ``=` `list``(``-``1` `for` `_ ``in` `range``(``2` `*` `N))`   `        ``flow ``=` `invert_path(graph, predecessor, flow, s, t)` `        ``first_node ``=` `flow[t]` `    ``else``:` `        ``print``(``"No cycle"``)` `        ``return`   `    ``# Find second path` `    ``predecessor ``=` `bfs(graph, s, t)` `    ``if` `predecessor ``is` `not` `None``:`   `        ``flow ``=` `invert_path(graph, predecessor, flow, s, t)` `        ``# Combine both paths:`   `        ``# From T to S` `        ``path1 ``=` `flow_path(flow, first_node, s)`   `        ``path2 ``=` `flow_path(flow, flow[t], s)` `        ``# Reverse the second path` `        ``# so we will  have another path` `        ``# but from s to t` `        ``path2.reverse()`   `        ``simpleCycle ``=` `[s]``+``path2``+``[t]``+``path1``+``[s]` `        ``print``(simpleCycle[::``2``])`   `    ``else``:` `        ``print``(``"No cycle"``)`     `# Driver Code` `if` `__name__ ``=``=` `"__main__"``:` `    ``graph ``=` `[` `        ``[``1``, ``6``],       ``# 0` `        ``[``0``, ``2``, ``3``],     ``# 1` `        ``[``1``, ``3``, ``5``, ``6``],   ``# 2` `        ``[``1``, ``2``, ``4``],     ``# 3` `        ``[``3``, ``5``],       ``# 4` `        ``[``2``, ``4``],       ``# 5` `        ``[``0``, ``2``],       ``# 6`   `    ``]` `    ``cycleWith2Nodes(graph, s ``=` `0``, t ``=` `4``)`

## Java

 `import` `java.util.*;`   `public` `class` `CycleBetweenVertices {` `    `  `    ``static` `int` `N;` `    ``static` `List[] graph;` `    ``static` `int``[] parent;` `    ``static` `boolean``[] visited;` `    ``static` `boolean` `foundCycle;` `    ``static` `List cycle;` `    ``static` `int` `S, T;` `    `  `    ``public` `static` `List findCycle(``int` `n, ``int``[][] edges, ``int` `s, ``int` `t) {` `        ``N = n;` `        ``graph = ``new` `List[N];` `        ``parent = ``new` `int``[N];` `        ``visited = ``new` `boolean``[N];` `        ``foundCycle = ``false``;` `        ``cycle = ``new` `ArrayList<>();` `        ``S = s;` `        ``T = t;` `        `  `        ``for` `(``int` `i = ``0``; i < N; i++) {` `            ``graph[i] = ``new` `ArrayList<>();` `            ``parent[i] = -``1``;` `        ``}` `        `  `        ``for` `(``int``[] edge : edges) {` `            ``int` `u = edge[``0``];` `            ``int` `v = edge[``1``];` `            ``graph[u].add(v);` `            ``graph[v].add(u);` `        ``}` `        `  `        ``dfs(S, -``1``);` `        `  `        ``if` `(!foundCycle) {` `            ``return` `new` `ArrayList<>();` `        ``}` `        `  `        ``Collections.reverse(cycle);` `        ``return` `cycle;` `    ``}` `    `  `    ``public` `static` `boolean` `dfs(``int` `u, ``int` `p) {` `        ``visited[u] = ``true``;` `        ``parent[u] = p;` `        `  `        ``for` `(``int` `v : graph[u]) {` `            ``if` `(foundCycle) {` `                ``return` `true``;` `            ``}` `            `  `            ``if` `(!visited[v]) {` `                ``if` `(dfs(v, u)) {` `                    ``return` `true``;` `                ``}` `            ``} ``else` `if` `(v != p && (v == S || v == T)) {` `                ``foundCycle = ``true``;` `                ``cycle.add(v);` `                ``for` `(``int` `i = u; i != v; i = parent[i]) {` `                    ``cycle.add(i);` `                ``}` `                ``cycle.add(v);` `                ``return` `true``;` `            ``}` `        ``}` `        `  `        ``return` `false``;` `    ``}` `    `  `    ``public` `static` `void` `main(String[] args) {` `        ``int` `n = ``7``;` `        ``int``[][] edges = {{``0``, ``1``}, {``1``, ``2``}, {``1``, ``6``}, {``2``, ``3``}, {``3``, ``4``}, {``4``, ``5``}, {``5``, ``2``}, {``2``, ``6``}, {``6``, ``0``}};` `        ``int` `s = ``0``;` `        ``int` `t = ``4``;` `        `  `        ``List cycle = findCycle(n, edges, s, t);` `        `  `        ``if` `(cycle.isEmpty()) {` `            ``System.out.println(``"No cycle exists between "` `+ s + ``" and "` `+ t + ``"."``);` `        ``} ``else` `{` `            ``System.out.print(``"Cycle between "` `+ s + ``" and "` `+ t + ``": "``);` `            ``for` `(``int` `i = ``0``; i < cycle.size(); i++) {` `                ``System.out.print(cycle.get(i));` `                ``if` `(i < cycle.size() - ``1``) {` `                    ``System.out.print(``" -> "``);` `                ``}` `            ``}` `            ``System.out.println();` `        ``}` `    ``}` `}`   `//This code is contributed by Akash Jha`

## C++

 `#include ` `using` `namespace` `std;`   `int` `N;` `vector<``int``> graph;` `int` `parent;` `bool` `visited;` `bool` `foundCycle;` `vector<``int``> cycle;` `int` `S, T;`   `bool` `dfs(``int` `u, ``int` `p);`   `vector<``int``> findCycle(``int` `n, vector>& edges, ``int` `s, ``int` `t) {` `    ``N = n;` `    ``foundCycle = ``false``;` `    ``cycle.clear();` `    ``S = s;` `    ``T = t;`   `    ``for` `(``int` `i = 0; i < N; i++) {` `        ``graph[i].clear();` `        ``parent[i] = -1;` `        ``visited[i] = ``false``;` `    ``}`   `    ``for` `(``auto` `edge : edges) {` `        ``int` `u = edge;` `        ``int` `v = edge;` `        ``graph[u].push_back(v);` `        ``graph[v].push_back(u);` `    ``}`   `    ``dfs(S, -1);`   `    ``if` `(!foundCycle) {` `        ``return` `vector<``int``>();` `    ``}`   `    ``reverse(cycle.begin(), cycle.end());` `    ``return` `cycle;` `}`   `bool` `dfs(``int` `u, ``int` `p) {` `    ``visited[u] = ``true``;` `    ``parent[u] = p;`   `    ``for` `(``auto` `v : graph[u]) {` `        ``if` `(foundCycle) {` `            ``return` `true``;` `        ``}`   `        ``if` `(!visited[v]) {` `            ``if` `(dfs(v, u)) {` `                ``return` `true``;` `            ``}` `        ``} ``else` `if` `(v != p && (v == S || v == T)) {` `            ``foundCycle = ``true``;` `            ``cycle.push_back(v);` `            ``for` `(``int` `i = u; i != v; i = parent[i]) {` `                ``cycle.push_back(i);` `            ``}` `            ``cycle.push_back(v);` `            ``return` `true``;` `        ``}` `    ``}`   `    ``return` `false``;` `}`     `int` `main() {` `    ``int` `n = 7;` `    ``vector> edges = {{0, 1}, {1, 2}, {1, 6}, {2, 3}, {3, 4}, {4, 5}, {5, 2}, {2, 6}, {6, 0}};` `    ``int` `s = 0;` `    ``int` `t = 4;`   `    ``vector<``int``> cycle = findCycle(n, edges, s, t);`   `    ``if` `(cycle.empty()) {` `        ``cout << ``"No cycle exists between "` `<< s << ``" and "` `<< t << ``"."` `<< endl;` `    ``} ``else` `{` `        ``cout << ``"Cycle between "` `<< s << ``" and "` `<< t << ``": "``;` `        ``for` `(``int` `i = 0; i < cycle.size(); i++) {` `            ``cout << cycle[i];` `            ``if` `(i < cycle.size() - 1) {` `                ``cout << ``" -> "``;` `            ``}` `        ``}` `        ``cout << endl;` `    ``}` `    ``return` `0;` `}`   `//This code is contributed by Akash Jha`

## C#

 `using` `System;` `using` `System.Collections.Generic;` `using` `System.Linq;`   `class` `Program {` `    ``static` `int` `N;` `    ``static` `List<``int``>[] graph;` `    ``static` `int``[] parent;` `    ``static` `bool``[] visited;` `    ``static` `bool` `foundCycle;` `    ``static` `List<``int``> cycle;` `    ``static` `int` `S, T;`   `    ``static` `bool` `dfs(``int` `u, ``int` `p) {` `        ``visited[u] = ``true``;` `        ``parent[u] = p;`   `        ``foreach` `(``int` `v ``in` `graph[u]) {` `            ``if` `(foundCycle) {` `                ``return` `true``;` `            ``}`   `            ``if` `(!visited[v]) {` `                ``if` `(dfs(v, u)) {` `                    ``return` `true``;` `                ``}` `            ``} ``else` `if` `(v != p && (v == S || v == T)) {` `                ``foundCycle = ``true``;` `                ``cycle.Add(v);` `                ``for` `(``int` `i = u; i != v; i = parent[i]) {` `                    ``cycle.Add(i);` `                ``}` `                ``cycle.Add(v);` `                ``return` `true``;` `            ``}` `        ``}`   `        ``return` `false``;` `    ``}`   `    ``static` `List<``int``> FindCycle(``int` `n, ``int``[][] edges, ``int` `s, ``int` `t) {` `        ``N = n;` `        ``foundCycle = ``false``;` `        ``cycle = ``new` `List<``int``>();` `        ``S = s;` `        ``T = t;`   `        ``graph = ``new` `List<``int``>[N];` `        ``parent = ``new` `int``[N];` `        ``visited = ``new` `bool``[N];`   `        ``for` `(``int` `i = 0; i < N; i++) {` `            ``graph[i] = ``new` `List<``int``>();` `            ``parent[i] = -1;` `            ``visited[i] = ``false``;` `        ``}`   `        ``foreach` `(``var` `edge ``in` `edges) {` `            ``int` `u = edge;` `            ``int` `v = edge;` `            ``graph[u].Add(v);` `            ``graph[v].Add(u);` `        ``}`   `        ``dfs(S, -1);`   `        ``if` `(!foundCycle) {` `            ``return` `new` `List<``int``>();` `        ``}`   `        ``cycle.Reverse();` `        ``return` `cycle;` `    ``}`   `    ``static` `void` `Main(``string``[] args) {` `        ``int` `n = 7;` `        ``int``[][] edges = ``new` `int``[][] {` `            ``new` `int``[] {0, 1},` `            ``new` `int``[] {1, 2},` `            ``new` `int``[] {1, 6},` `            ``new` `int``[] {2, 3},` `            ``new` `int``[] {3, 4},` `            ``new` `int``[] {4, 5},` `            ``new` `int``[] {5, 2},` `            ``new` `int``[] {2, 6},` `            ``new` `int``[] {6, 0},` `        ``};` `        ``int` `s = 0;` `        ``int` `t = 4;`   `        ``List<``int``> cycle = FindCycle(n, edges, s, t);`   `        ``if` `(cycle.Count == 0) {` `            ``Console.WriteLine(\$``"No cycle exists between {s} and {t}."``);` `        ``} ``else` `{` `            ``Console.Write(\$``"Cycle between {s} and {t}: "``);` `            ``Console.WriteLine(``string``.Join(``" -> "``, cycle));` `        ``}` `    ``}` `}` `//This code is contributed by AKash Jha`

## Javascript

 `let N;` `let graph = ``new` `Array(10001).fill().map(() => []);` `let parent = ``new` `Array(10001).fill(-1);` `let visited = ``new` `Array(10001).fill(``false``);` `let foundCycle;` `let cycle;` `let S, T;`   `function` `findCycle(n, edges, s, t) {` `    ``N = n;` `    ``foundCycle = ``false``;` `    ``cycle = [];` `    ``S = s;` `    ``T = t;`   `    ``for` `(let i = 0; i < N; i++) {` `        ``graph[i].length = 0;` `        ``parent[i] = -1;` `        ``visited[i] = ``false``;` `    ``}`   `    ``for` `(let edge of edges) {` `        ``let u = edge;` `        ``let v = edge;` `        ``graph[u].push(v);` `        ``graph[v].push(u);` `    ``}`   `    ``dfs(S, -1);`   `    ``if` `(!foundCycle) {` `        ``return` `[];` `    ``}`   `    ``cycle.reverse();` `    ``return` `cycle;` `}`   `function` `dfs(u, p) {` `    ``visited[u] = ``true``;` `    ``parent[u] = p;`   `    ``for` `(let v of graph[u]) {` `        ``if` `(foundCycle) {` `            ``return` `true``;` `        ``}`   `        ``if` `(!visited[v]) {` `            ``if` `(dfs(v, u)) {` `                ``return` `true``;` `            ``}` `        ``} ``else` `if` `(v !== p && (v === S || v === T)) {` `            ``foundCycle = ``true``;` `            ``cycle.push(v);` `            ``for` `(let i = u; i !== v; i = parent[i]) {` `                ``cycle.push(i);` `            ``}` `            ``cycle.push(v);` `            ``return` `true``;` `        ``}` `    ``}`   `    ``return` `false``;` `}`   `let n = 7;` `let edges = [[0, 1], [1, 2], [1, 6], [2, 3], [3, 4], [4, 5], [5, 2], [2, 6], [6, 0]];` `let s = 0;` `let t = 4;`   `let cycleResult = findCycle(n, edges, s, t);`   `if` `(cycleResult.length === 0) {` `    ``console.log(``"No cycle exists between "` `+ s + ``" and "` `+ t + ``"."``);` `} ``else` `{` `    ``console.log(``"Cycle between "` `+ s + ``" and "` `+ t + ``": "``);` `    ``for` `(let i = 0; i < cycleResult.length; i++) {` `        ``console.log(cycleResult[i]);` `        ``if` `(i < cycleResult.length - 1) {` `            ``console.log(``" -> "``);` `        ``}` `    ``}` `    ``console.log();` `}` `//This code is contributed by Akash Jha`

Output

`[0, 6, 2, 5, 4, 3, 1, 0]`

Complexity Analysis: Given below are the complexity for each function

1. Create duplicate graph: O(V+E)
2. 2 BFS:  O(V+E)
3. 2 inversions (registering flow) : O(path size) <= O(V+E)
4. Recreate the paths from the flow array: O(path size) <= O(V+E)
5. Reverse one path:  O(path size) <= O(V+E)

Time Complexity: O(V+E)
Auxiliary Space: O(N*N), where N is the count of vertices in the graph.

My Personal Notes arrow_drop_up