You are given a directed graph of n nodes numbered from 0 to n - 1, where each node has at most one outgoing edge.
The graph is represented with a given 0-indexed array edges of size n, indicating that there is a directed edge from node i to node edges[i]. If there is no outgoing edge from node i, then edges[i] == -1.
Return the length of the longest cycle in the graph. If no cycle exists, return -1.
A cycle is a path that starts and ends at the same node.
Input: edges = [3,3,4,2,3]
Output: 3
Explanation: The longest cycle in the graph is the cycle: 2 -> 4 -> 3 -> 2.
The length of this cycle is 3, so 3 is returned.
Example 2:
graph LR
0 --> 2 --> 3 --> 1
1
2
3
Input: edges = [2,-1,3,1]
Output: -1
Explanation: There are no cycles in this graph.
The main idea is to use DFS to traverse the graph and track the visit time of each node during the current path. If we revisit a node that is already in the current path, we have found a cycle, and the cycle’s length is the difference between the current time and the time when we first visited that node. By marking nodes as globally visited, we avoid redundant work.
classSolution {
public:int longestCycle(vector<int>& edges) {
int n = edges.size(), ans =-1;
vector<bool> vis(n, false);
for (int i =0; i < n; ++i) {
if (vis[i]) continue;
unordered_map<int, int> mp;
int cur = i, dist =0;
while (cur !=-1) {
if (mp.count(cur)) {
ans = max(ans, dist - mp[cur]);
break;
}
if (vis[cur]) break;
vis[cur] = true;
mp[cur] = dist++;
cur = edges[cur];
}
}
return ans;
}
};
classSolution {
publicintlongestCycle(int[] edges) {
boolean[] visited =newboolean[edges.length];
int ans =-1;
for (int i = 0; i < edges.length; i++) {
if (visited[i]) continue;
Map<Integer, Integer> map =new HashMap<>();
int cur = i, dist = 0;
while (cur !=-1) {
if (map.containsKey(cur)) {
ans = Math.max(ans, dist - map.get(cur));
break;
}
if (visited[cur]) break;
visited[cur]=true;
map.put(cur, dist++);
cur = edges[cur];
}
}
return ans;
}
}
classSolution {
funlongestCycle(edges: IntArray): Int {
val n = edges.size
val vis = BooleanArray(n)
var ans = -1for (i in0 until n) {
if (vis[i]) continueval mp = mutableMapOf<Int, Int>()
var cur = i
var dist = 0while (cur != -1) {
if (mp.containsKey(cur)) {
ans = maxOf(ans, dist - mp[cur]!!)
break }
if (vis[cur]) break vis[cur] = true mp[cur] = dist++ cur = edges[cur]
}
}
return ans
}
}
classSolution:
deflongestCycle(self, edges: list[int]) -> int:
n = len(edges)
vis = [False] * n
ans =-1for i in range(n):
if vis[i]:
continue mp = dict()
cur, dist = i, 0while cur !=-1:
if cur in mp:
ans = max(ans, dist - mp[cur])
breakif vis[cur]:
break vis[cur] =True mp[cur] = dist
dist +=1 cur = edges[cur]
return ans
impl Solution {
pubfnlongest_cycle(edges: Vec<i32>) -> i32 {
let n = edges.len();
letmut vis =vec![false; n];
letmut ans =-1;
for i in0..n {
if vis[i] { continue; }
letmut mp = std::collections::HashMap::new();
letmut cur = i;
letmut dist =0;
while cur !=usize::MAX&& cur < n {
iflet Some(&v) = mp.get(&cur) {
ans = ans.max(dist - v);
break;
}
if vis[cur] { break; }
vis[cur] =true;
mp.insert(cur, dist);
dist +=1;
let next = edges[cur];
if next ==-1 {
cur =usize::MAX;
} else {
cur = next asusize;
}
}
}
ans asi32 }
}