This commit is contained in:
Nathan Wang 2020-06-03 17:38:34 -07:00
commit 6db2450f06
4 changed files with 112 additions and 48 deletions

View file

@ -1,32 +1,35 @@
# Silver - Graphs # Silver - DFS
Author: Siyong Huang Author: Siyong Huang
## Overview ## Overview
- Prerequisites - Prerequisites
- Depth First Search (DFS) - Depth First Search (DFS)
- Flood Fill - Flood Fill
- Graph Two-Coloring - Graph Two-Coloring
- Cycle Detection - Cycle Detection
## Prerequisites ## Prerequisites
- [Graph Theory](https://csacademy.com/lesson/introduction_to_graphs) - [CSAcademy Graph Theory](https://csacademy.com/lesson/introduction_to_graphs)
- [Graph Representations](https://csacademy.com/lesson/graph_representation) - [CSAcademy Graph Representations](https://csacademy.com/lesson/graph_representation)
- Note: DFS is most commonly implemented with adjacency lists - Note: DFS is most commonly implemented with adjacency lists.
## Depth First Search (DFS) ## Depth First Search (DFS)
*Depth First Search*, more commonly DFS, is a fundamental graph algorithm that traverses an entire connected component. The rest of this document describe various applications of DFS. *Depth First Search*, more commonly DFS, is a fundamental graph algorithm that traverses an entire connected component. The rest of this document describes various applications of DFS. Of course, it is one possible way to implement flood fill. *Breadth first search* (BFS) is **not** required for silver.
- [CSES Building Roads](https://cses.fi/problemset/task/1666)
### Tutorial ### Tutorial
- Recommended: - Recommended:
- [CSAcademy BFS](https://csacademy.com/lesson/depth_first_search/) - [CSAcademy DFS](https://csacademy.com/lesson/depth_first_search/)
- Additional: - Additional:
- CPH Chapter 12 - CPH Chapter 12
- [cp-algo DFS](https://cp-algorithms.com/graph/depth-first-search.html) - [cp-algo DFS](https://cp-algorithms.com/graph/depth-first-search.html)
- hard to parse if this is your first time learning about DFS
### Problems ### Problems
@ -38,7 +41,10 @@ Author: Siyong Huang
## Flood Fill ## Flood Fill
*Flood Fill* refers to finding the number of connected components in a graph, frequently on a grid. *Flood Fill* refers to finding the number of connected components in a graph, usually when the graph is a grid.
- [CSES Counting Rooms](https://cses.fi/problemset/task/1192)
- [CSES Labyrinth](https://cses.fi/problemset/task/1193)
### Tutorial ### Tutorial
@ -56,13 +62,17 @@ Author: Siyong Huang
## Graph Two-Coloring ## Graph Two-Coloring
*Graph two-colorings* is assigning a boolean value to each node of the graph, dictated by the edge configuration *Graph two-colorings* is assigning a boolean value to each node of the graph, dictated by the edge configuration
The most common example of a two-colored graph is a *bipartite graph*, in which each edge connects two nodes of opposite colors The most common example of a two-colored graph is a *bipartite graph*, in which each edge connects two nodes of opposite colors.
- [CSES Building Teams](https://cses.fi/problemset/task/1668)
### Tutorial ### Tutorial
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)
{ {
@ -83,7 +93,7 @@ void dfs(int node)
- Additional: - Additional:
- [Bipartite Graphs: cp-alg bipartite check](https://cp-algorithms.com/graph/bipartite-check.html) - [Bipartite Graphs: cp-alg bipartite check](https://cp-algorithms.com/graph/bipartite-check.html)
- Note: CP Algorithm uses bfs, but dfs accomplishes the same task - Note: CP-Algorithms uses BFS, but DFS accomplishes the same task
### Problems ### Problems
@ -91,18 +101,28 @@ void dfs(int node)
## Cycle Detection ## Cycle Detection
A *cycle* is a non-empty path of distinct edges that start and end at the same 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 or just checking whether a cycle exists.
*Cycle detection* determines properties of cycles in a graph, such as counting the number of cycles in a graph or determining whether a node is in a cycle. For most silver-level cycle problems, each node has only one out-degree, meaning that it's adjacency list is of size 1. If this is not the case, the problem generalizes to *Strongly Connected Components*, a platinum level concept.
### Tutorial A related topic is **strongly connected components**, a platinum level concept.
The following sample code counts the number of cycles in a graph where each node points to one other node. 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. ### 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.
```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;
@ -122,10 +142,58 @@ int main()
} }
``` ```
The same general idea is implemented below to find any cycle in a directed graph (if one exists).
```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
- [Codeforces 1020B. Badge (Very Easy)](https://codeforces.com/contest/1020/problem/B) - [Codeforces 1020B. Badge (Very Easy)](https://codeforces.com/contest/1020/problem/B)
- Try to solve the problem in O(N)! - Try to solve the problem in O(N)!
- [The Bovine Shuffle (Normal)](http://usaco.org/index.php?page=viewproblem2&cpid=764) - [The Bovine Shuffle (Normal)](http://usaco.org/index.php?page=viewproblem2&cpid=764)
- [Swapity Swapity Swap (Very Hard)](http://www.usaco.org/index.php?page=viewproblem2&cpid=1014) - [Swapity Swapity Swap (Very Hard)](http://www.usaco.org/index.php?page=viewproblem2&cpid=1014)
- [CSES Round Trip (undirected)](https://cses.fi/problemset/task/1669)
- [CSES Round Trip II (directed)](https://cses.fi/problemset/task/1678)

View file

@ -70,5 +70,6 @@ Hasn't appeared in recent USACO Gold as far as I know.
* [CSES High Score](https://cses.fi/problemset/task/1673) * [CSES High Score](https://cses.fi/problemset/task/1673)
* [Kattis SSSP Negative](https://open.kattis.com/problems/shortestpath3) * [Kattis SSSP Negative](https://open.kattis.com/problems/shortestpath3)
* [CSES Cycle Finding](https://cses.fi/problemset/task/1197)
Can also modify Dijkstra's so it works with negative edge weights (but not negative cycles). The same running time bound no longer applies. Can also modify Dijkstra's so it works with negative edge weights (but not negative cycles). The same running time bound no longer applies.

View file

@ -16,7 +16,7 @@ From the latter link (modified):
> * It can be divided into multiple sections, where each section is a linear function (usually) with an integer slope. > * It can be divided into multiple sections, where each section is a linear function (usually) with an integer slope.
> * It is a convex/concave function. In other words, the slope of each section is non-decreasing or non-increasing when scanning the function from left to right. > * It is a convex/concave function. In other words, the slope of each section is non-decreasing or non-increasing when scanning the function from left to right.
It's generally applicable as a DP optimization. It's generally applicable as a DP optimization. Usually you can come up with a slower DP (ex. $O(N^2)$) first and then optimize it to $O(N\log N)$ with slope trick.
This document assumes some familiarity with at least one of the links above. This document assumes some familiarity with at least one of the links above.
@ -24,7 +24,7 @@ This document assumes some familiarity with at least one of the links above.
[CF Buy Low Sell High](https://codeforces.com/contest/866/problem/D) [CF Buy Low Sell High](https://codeforces.com/contest/866/problem/D)
Let $dp[i][j]$ denote the maximum amount of money you can have on day $i$ if you have exactly $j$ shares of stock on that day. The final answer will be $dp[N][0]$. This easily leads to an $O(N^2)$ DP. **Slow Solution**: Let $dp[i][j]$ denote the maximum amount of money you can have on day $i$ if you have exactly $j$ shares of stock on that day. The final answer will be $dp[N][0]$. This easily leads to an $O(N^2)$ DP.
Of course, we never used the fact that the DP is concave down! Specifically, let $dif[i][j]=dp[i][j]-dp[i][j+1]\ge 0$. Then $dif[i][j]\le dif[i][j+1]$ for all $j\ge 0$ (ignoring the case when we get $dp$ values of $-\infty$). Of course, we never used the fact that the DP is concave down! Specifically, let $dif[i][j]=dp[i][j]-dp[i][j+1]\ge 0$. Then $dif[i][j]\le dif[i][j+1]$ for all $j\ge 0$ (ignoring the case when we get $dp$ values of $-\infty$).
@ -69,9 +69,9 @@ int main() {
Let $dif_i=a_i-b_i$. Defining $d_j=\sum_{i=1}^jdif_i$, our goal is to move around the potatoes such that $d_0,d_1,\ldots,d_N$ is a non-decreasing sequence. Moving a potato is equivalent to changing exactly one of the $d_i$ (aside from $d_0,d_N$) by one. Let $dif_i=a_i-b_i$. Defining $d_j=\sum_{i=1}^jdif_i$, our goal is to move around the potatoes such that $d_0,d_1,\ldots,d_N$ is a non-decreasing sequence. Moving a potato is equivalent to changing exactly one of the $d_i$ (aside from $d_0,d_N$) by one.
As before, we can come up with a $O(N\cdot d_N)$ solution, where $dp[i][j]$ is the minimum cost to determine $d_0,d_1,\ldots,d_i$ such that $d_i\le j$. As before, this DP is concave up for a fixed $i$!! **Slow Solution:** Let $dp[i][j]$ be the minimum cost to determine $d_0,d_1,\ldots,d_i$ such that $d_i\le j$ for each $0\le j\le d_N$. This gives a $O(N\cdot d_N)$ solution.
So given a piecewise linear function $DP_x$, we need to support the following operations. As before, this DP is concave up for a fixed $i$! Given a piecewise linear function $DP_x$, we need to support the following operations.
* Add $|x-k|$ to the function for some $k$ * Add $|x-k|$ to the function for some $k$
* Set $DP_x=\min(DP_x,DP_{x-1})$ for all $x$ * Set $DP_x=\min(DP_x,DP_{x-1})$ for all $x$
@ -181,11 +181,11 @@ int main() {
## Problems ## Problems
* [Moving Haybales (USACO Camp)](https://probgate.org/viewproblem.php?pid=247)
* [Wall](https://atcoder.jp/contests/kupc2016/tasks/kupc2016_h) * [Wall](https://atcoder.jp/contests/kupc2016/tasks/kupc2016_h)
* same as potatoes * same as "Potatoes"
* [Stock Trading](https://probgate.org/viewproblem.php?pid=531&cid=81) * [Stock Trading (USACO Camp)](https://probgate.org/viewproblem.php?pid=531&cid=81)
* extension of buy low sell high * extension of "Buy Low Sell High"
* USACO Camp (private)
* [Bookface](https://codeforces.com/group/ZFgXbZSjvp/contest/274852/problem/C) * [Bookface](https://codeforces.com/group/ZFgXbZSjvp/contest/274852/problem/C)
* [CCDSAP Exam](https://www.codechef.com/problems/CCDSAP) * [CCDSAP Exam](https://www.codechef.com/problems/CCDSAP)
* [Farm of Monsters](https://codeforces.com/gym/102538/problem/F) * [Farm of Monsters](https://codeforces.com/gym/102538/problem/F)

View file

@ -37,46 +37,41 @@
- Standard Containers - Standard Containers
- ex. [Convention II](http://usaco.org/index.php?page=viewproblem2&cpid=859) - ex. [Convention II](http://usaco.org/index.php?page=viewproblem2&cpid=859)
- Sorting - Sorting
- Binary Search (BinSearch) - ex. [Counting Haybales](http://usaco.org/index.php?page=viewproblem2&cpid=666)
- ex. [Counting Haybales](http://usaco.org/index.php?page=viewproblem2&cpid=666) - Binary Search (BinSearch)
- ex. [Convention](http://usaco.org/index.php?page=viewproblem2&cpid=858)
- Two Pointers (2P) - Two Pointers (2P)
- ex. [Diamond Collector](http://usaco.org/index.php?page=viewproblem2&cpid=643) - ex. [Diamond Collector](http://usaco.org/index.php?page=viewproblem2&cpid=643)
- Prefix Sums (Psum) - Prefix Sums (Psum)
- ex. [Breed Counting](http://www.usaco.org/index.php?page=viewproblem2&cpid=572) - ex. [Breed Counting](http://www.usaco.org/index.php?page=viewproblem2&cpid=572)
- Flood Fill (FF) - DFS
- ex. [Switching on the Lights](http://www.usaco.org/index.php?page=viewproblem2&cpid=570) - ex. [Switching on the Lights](http://www.usaco.org/index.php?page=viewproblem2&cpid=570)
- Occasionally, graph problems appear in bronze ... - Occasionally, graph problems appear in bronze ...
- Permutations
- Cycle Decomposition?
- ex. [Swapity Swapity Swap](http://www.usaco.org/index.php?page=viewproblem2&cpid=1014)
# Gold # Gold
- Dynamic Programming (DP) - Dynamic Programming (DP)
- ex. [Time is Mooney](http://www.usaco.org/index.php?page=viewproblem2&cpid=993) - ex. [Time is Mooney](http://www.usaco.org/index.php?page=viewproblem2&cpid=993)
- Graphs - Shortest Path
- Breadth First Search (BFS) - Breadth First Search (BFS)
- ex. [Cow Navigation](http://www.usaco.org/index.php?page=viewproblem2&cpid=695) - ex. [Cow Navigation](http://www.usaco.org/index.php?page=viewproblem2&cpid=695)
- Shortest Path (SP) - Shortest Path (SP)
- ex. [Milk Pumping](http://www.usaco.org/index.php?page=viewproblem2&cpid=969) - ex. [Milk Pumping](http://www.usaco.org/index.php?page=viewproblem2&cpid=969)
- Minimum Spanning Tree (MST) - Minimum Spanning Tree (MST) & Disjoint Set Union (DSU)
- Disjoint Set Union (DSU) - ex. [Fencedin](http://www.usaco.org/index.php?page=viewproblem2&cpid=623)
- ex. [Fencedin](http://www.usaco.org/index.php?page=viewproblem2&cpid=623) - Topological Sort (TopoSort)
- Topological Sort (TopoSort) - ex. [Timeline](http://www.usaco.org/index.php?page=viewproblem2&cpid=1017)
- ex. [Timeline](http://www.usaco.org/index.php?page=viewproblem2&cpid=1017)
- [Range Sum Queries with Point Updates](https://thecodingwizard.github.io/usaco-training-2.0/Gold_1DRQ) - [Range Sum Queries with Point Updates](https://thecodingwizard.github.io/usaco-training-2.0/Gold_1DRQ)
- ex. [Haircut](http://www.usaco.org/index.php?page=viewproblem2&cpid=1041) - ex. [Haircut](http://www.usaco.org/index.php?page=viewproblem2&cpid=1041)
- Number Theory - Number Theory
- ex. [Cow Poetry](http://usaco.org/index.php?page=viewproblem2&cpid=897) - ex. [Cow Poetry](http://usaco.org/index.php?page=viewproblem2&cpid=897)
- Less Common - Hashing (NOT COMMON)
- Strings - ex. [Cownomics](http://www.usaco.org/index.php?page=viewproblem2&cpid=741)
- Hashing - Combinatorics (NOT COMMON)
- ex. [Cownomics](http://www.usaco.org/index.php?page=viewproblem2&cpid=741) - Principle of Inclusion and Exclusion (PIE)
- Combinatorics - ex. [Cowpatibility](http://usaco.org/index.php?page=viewproblem2&cpid=862)
- Principle of Inclusion and Exclusion (PIE) - Sliding Window (NOT COMMON)
- ex. [Cowpatibility](http://usaco.org/index.php?page=viewproblem2&cpid=862) - ex. [Haybale Feast](http://www.usaco.org/index.php?page=viewproblem2&cpid=767)
- Sliding Window
- ex. [Haybale Feast](http://www.usaco.org/index.php?page=viewproblem2&cpid=767)
# Platinum # Platinum