3.6 KiB
id | title | author | prerequisites | description | ||
---|---|---|---|---|---|---|
cyc | Cycle Detection & Functional Graphs | Siyong Huang |
|
A *cycle* is a non-empty path of distinct edges that start and end at the same node. (what about distinct vertices?) |
Cycle detection determines properties of cycles in a directed or undirected graph, such as whether each node of the graph is part of a cycle or just checking whether a cycle exists.
A related topic is strongly connected components, a platinum level concept.
Undirected Graphs
BFS-Cycle
Functional Graphs
Links:
- CPH 16.3: successor paths
- CPH 16.4: cycle detection in successor graph
In silver-level directed cycle problems, it is generally the case that each node has exactly one edge going out of it. This is known as a successor graph or a functional graph.
The following sample code counts the number of cycles in such a graph. The "stack" contains nodes that can reach the current node. If the current node points to a node v
on the stack (on_stack[v]
is true), then we know that a cycle has been created. However, if the current node points to a node v
that has been previously visited but is not on the stack, then we know that the current chain of nodes points into a cycle that has already been considered.
//UNTESTED
//Each node points to next_node[node]
bool visited[MAXN], on_stack[MAXN];
int number_of_cycles = 0, next_node[MAXN];
void dfs(int n)
{
visited[n] = on_stack[n] = true;
int u = next_node[n];
if(on_stack[u])
number_of_cycles++;
else if(!visited[u])
dfs(u);
on_stack[n] = false;
}
int main()
{
//read input, etc
for(int i = 1;i <= N;i++)
if(!visited[i])
dfs(i);
}
Directed Graphs
The same general idea is implemented below to find any cycle in a directed graph (if one exists).
//UNTESTED
bool visited[MAXN], on_stack[MAXN];
vector<int> adj[MAXN];
vector<int> cycle;
bool dfs(int n)
{
visited[n] = on_stack[n] = true;
for(int u:adj[n])
{
if(on_stack[u])
return cycle.push_back(v), cycle.push_back(u), on_stack[n] = on_stack[u] = false, true;
else if(!visited[u])
{
if(dfs(u))
if(on_stack[n])
return cycle.push_back(n), on_stack[n] = false, true;
else
return false;
if(!cycle.empty())
return false;
}
}
on_stack[n] = false;
return false;
}
int main()
{
//take input, etc
for(int i = 1;cycle.empty() && i <= N;i++)
dfs(i);
if(cycle.empty())
printf("No cycle found!\n");
else
{
reverse(cycle.begin(), cycle.end());
printf("Cycle of length %u found!\n", cycle.size());
for(int n : cycle) printf("%d ", n);
printf("\n");
}
}
Problems
- CSES
- Codeforces 1020B. Badge (Very Easy)
- Try to solve the problem in
O(N)
!
- Try to solve the problem in
- USACO Silver
- Note that these graphs are special.
- The Bovine Shuffle (Normal)
- functional graph
- Swapity Swapity Swap (Very Hard)
- permutation
- POI