116 lines
3.6 KiB
Text
116 lines
3.6 KiB
Text
---
|
|
id: func-graphs
|
|
title: Functional Graphs
|
|
author: Siyong Huang
|
|
prerequisites:
|
|
- dfs
|
|
description: "Properties of a functional graphs, directed graphs in which every vertex has exactly one outgoing edge."
|
|
frequency: 1
|
|
---
|
|
|
|
|
|
import { Problem } from "../models";
|
|
|
|
export const metadata = {
|
|
problems: {
|
|
sample: [
|
|
new Problem("CF", "Div 2 B - Badge", "contest/1020/problem/B", "Very Easy", false, ["Func Graph"], "Try to solve the problem in $O(N)$!"),
|
|
],
|
|
general: [
|
|
new Problem("Silver", "The Bovine Shuffle", "764", "Normal", false, ["Func Graph"], "Try to solve the problem in $O(N)$!"),
|
|
new Problem("CSES", "Planets Cycles", "1751", "Normal", false, ["Func Graph"], ""),
|
|
new Problem("Silver", "Swapity Swapity Swap", "1014", "Normal", false, ["Permutation"], ""),
|
|
new Problem("Codeforces", "Cooperative Game", "https://codeforces.com/contest/1137/problem/D", "Normal", false, ["Func Graph, Floyd's Algorithm"], "Implement Floyd's Algorithm! (You only actually need 3 friends to solve the problem!)"),
|
|
new Problem("POI", "Mafia", "https://szkopul.edu.pl/problemset/problem/w3YAoAT3ej27YeiaNWjK57_G/site/?key=statement", "Hard", false, ["Func Graph"], ""),
|
|
new Problem("POI", "Spies", "https://szkopul.edu.pl/problemset/problem/r6tMTfvQFPAEfQioYMCQndQe/site/?key=statement", "Hard", false, [], ""),
|
|
new Problem("POI", "Frog", "https://szkopul.edu.pl/problemset/problem/qDH9CkBHZKHY4vbKRBlXPrA7/site/?key=statement", "Hard", false, [], ""),
|
|
],
|
|
}
|
|
};
|
|
|
|
We'll consider graphs like the one presented in this problem:
|
|
|
|
<Problems problems={metadata.problems.sample} />
|
|
|
|
< br/>
|
|
|
|
Aka **successor graph**.
|
|
|
|
<Resources>
|
|
<Resource source="CPH" title="16.3, 16.4 - Successor Graphs"></Resource>
|
|
</Resources>
|
|
|
|
## Implementation
|
|
|
|
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.
|
|
|
|
<LanguageSection>
|
|
|
|
<CPPSection>
|
|
|
|
```cpp
|
|
//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);
|
|
}
|
|
```
|
|
|
|
</CPPSection>
|
|
|
|
</LanguageSection>
|
|
|
|
## Tortoise and Hare (Floyd's Algorithm)
|
|
|
|
**Floyd's Algorithm**, also commonly referred to as the **Tortoise and Hare Algorithm**, is capable of detecting cycles in a functional graph in $O(N)$ time and $O(1)$ memory (not counting the graph itself)
|
|
|
|
```cpp
|
|
//UNTESTED
|
|
pair<int, int> detect_cycle(int *next, int start_node) //return pair(length of cycle, distance from start node to in cycle)
|
|
{
|
|
int t=start_node, h=start_node; //tortoise and hare
|
|
do
|
|
{
|
|
t=next[t], h=next[h];
|
|
} while(t != h)
|
|
|
|
int dist=0;
|
|
t = start_node;
|
|
while(t != h)
|
|
++dist, t=next[t], h=next[h];
|
|
|
|
int len=1;
|
|
h = next[t];
|
|
while(h != t)
|
|
++len, h=next[h];
|
|
return make_pair(len, dist);
|
|
}
|
|
```
|
|
|
|
<Resources>
|
|
<Resource source="Medium" title="The Tortoise and the Hare (Floyd's Algorithm)" url="https://medium.com/@tuvo1106/the-tortoise-and-the-hare-floyds-algorithm-87badf5f7d41"></Resource>
|
|
</Resources>
|
|
|
|
<IncompleteSection />
|
|
|
|
## Problems
|
|
|
|
<Problems problems={metadata.problems.general} />
|