Update Silver_Graphs.md
This commit is contained in:
commit
899e268871
1 changed files with 52 additions and 6 deletions
|
@ -71,6 +71,8 @@ The most common example of a two-colored graph is a *bipartite graph*, in which
|
||||||
The idea is that we can arbitrarily label a node and then run DFS. Every time we visit a new (unvisited) node, we set its color based on the edge rule. When we visit a previously visited node, check to see whether its color matches the edge rule. For example, an implementation of coloring a bipartite graph is shown below.
|
The idea is that we can arbitrarily label a node and then run DFS. Every time we visit a new (unvisited) node, we set its color based on the edge rule. When we visit a previously visited node, check to see whether its color matches the edge rule. For example, an implementation of coloring a bipartite graph is shown below.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
//UNTESTED
|
||||||
|
|
||||||
bool is_bipartite = true;
|
bool is_bipartite = true;
|
||||||
void dfs(int node)
|
void dfs(int node)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +103,8 @@ void dfs(int node)
|
||||||
|
|
||||||
A *cycle* is a non-empty path of distinct edges that start and end at the same node. *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.
|
A *cycle* is a non-empty path of distinct edges that start and end at the same node. *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.
|
||||||
|
|
||||||
|
A related topic is **strongly connected components**, a platinum level concept.
|
||||||
|
|
||||||
### Functional Graphs
|
### Functional Graphs
|
||||||
|
|
||||||
Links:
|
Links:
|
||||||
|
@ -112,13 +116,13 @@ In silver-level directed cycle problems, it is generally the case that each node
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
(test code?)
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
//UNTESTED
|
||||||
|
|
||||||
//Each node points to next_node[node]
|
//Each node points to next_node[node]
|
||||||
|
|
||||||
bool visited[MAXN], on_stack[MAXN];
|
bool visited[MAXN], on_stack[MAXN];
|
||||||
int number_of_cycles = 0;
|
int number_of_cycles = 0, next_node[MAXN];
|
||||||
void dfs(int n)
|
void dfs(int n)
|
||||||
{
|
{
|
||||||
visited[n] = on_stack[n] = true;
|
visited[n] = on_stack[n] = true;
|
||||||
|
@ -138,7 +142,51 @@ int main()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For non-functional directed graphs, this code will still detect a cycle if it exists (though `number_of_cycles` will be meaningless).
|
The same general idea is implemented below to find any cycle in a directed graph.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
//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
|
### Problems
|
||||||
|
|
||||||
|
@ -149,5 +197,3 @@ For non-functional directed graphs, this code will still detect a cycle if it ex
|
||||||
- [CSES Round Trip (undirected)](https://cses.fi/problemset/task/1669)
|
- [CSES Round Trip (undirected)](https://cses.fi/problemset/task/1669)
|
||||||
- [CSES Round Trip II (directed)](https://cses.fi/problemset/task/1678)
|
- [CSES Round Trip II (directed)](https://cses.fi/problemset/task/1678)
|
||||||
|
|
||||||
|
|
||||||
Cycle finding is also related to **strongly connected components**, a platinum level concept.
|
|
||||||
|
|
Reference in a new issue