GeeksforGeeks 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[10001];``int` `parent[10001];``bool` `visited[10001];``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[0];``        ``int` `v = edge[1];``        ``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[0];``            ``int` `v = edge[1];``            ``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[0];``        ``let v = edge[1];``        ``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