Wrote out Centroid, Added to Custom_Cpp_STL
also added problem to func_graphs but it will probably be taken out as I am still unable to solve it even after being told solution
This commit is contained in:
parent
f2a6ac2409
commit
8851ff6a59
|
@ -5,7 +5,7 @@ author: Siyong Huang, Benjamin Qi
|
||||||
prerequisites:
|
prerequisites:
|
||||||
- sorting-custom
|
- sorting-custom
|
||||||
- intro-ordered
|
- intro-ordered
|
||||||
description: "?"
|
description: "More ways to write custom comparators in C++ and incorporating them into STL objects."
|
||||||
frequency: 1
|
frequency: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ int main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Comparator
|
## Comparator
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
@ -67,10 +66,20 @@ int main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<Info title="Pro Tip" >
|
||||||
|
|
||||||
|
You can also use the following syntax to declare set `v` using a function
|
||||||
|
|
||||||
|
`set<Edge,decltype(*cmp)> v(cmp);`
|
||||||
|
|
||||||
|
</Info>
|
||||||
|
|
||||||
Lambda expressions also work:
|
Lambda expressions also work:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
auto cmp = [](const Edge& x, const Edge& y) { return x.w < y.w; };
|
auto cmp = [](const Edge& x, const Edge& y) { return x.w < y.w; };
|
||||||
|
//The real type of cmp is function<bool(const Edge&, const Edge&)>
|
||||||
|
//auto is used for short
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int M = 4;
|
int M = 4;
|
||||||
|
@ -83,7 +92,13 @@ int main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this case, we can shorten the declaration of `v` by writing `set<Edge,decltype(cmp)> v(cmp);` instead.
|
<Info title="Pro Tip" >
|
||||||
|
|
||||||
|
You can also use the following syntax to declare set `v` using a lambda
|
||||||
|
|
||||||
|
`set<Edge,decltype(cmp)> v(cmp);`
|
||||||
|
|
||||||
|
</Info>
|
||||||
|
|
||||||
## Functors
|
## Functors
|
||||||
|
|
||||||
|
@ -127,9 +142,17 @@ int main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<Info title="Pro Tip">
|
||||||
|
|
||||||
|
One functor can be used for multiple objects. Just keep overloading the `()` operator!
|
||||||
|
|
||||||
|
</Info>
|
||||||
|
|
||||||
## Built-In Functors
|
## Built-In Functors
|
||||||
|
|
||||||
Overloading the less than operator (`<`) automatically generates the functor `less<Edge>`. Similarly, overloading `>` automatically generates the functor [`greater<Edge>`](https://en.cppreference.com/w/cpp/utility/functional/greater). We can use this to store a set in reverse order.
|
Overloading the less than operator (`<`) automatically generates the functor [`less<Edge>`](https://en.cppreference.com/w/cpp/utility/functional/less).
|
||||||
|
Similarly, overloading (`>`) automatically generates the functor [`greater<Edge>`](https://en.cppreference.com/w/cpp/utility/functional/greater).
|
||||||
|
We can use this to store a set in reverse order.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <bits/stdc++.h>
|
#include <bits/stdc++.h>
|
||||||
|
@ -167,3 +190,16 @@ set<int,greater<int>> a;
|
||||||
map<int,string,greater<int>> b;
|
map<int,string,greater<int>> b;
|
||||||
priority_queue<int,vector<int>,greater<int>> c;
|
priority_queue<int,vector<int>,greater<int>> c;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<Warning title="Priority Queues">
|
||||||
|
|
||||||
|
In C++, priority queues are sorted in decreasing order.
|
||||||
|
Specifically, larger elements have higher 'priority' and are popped first.
|
||||||
|
|
||||||
|
If you want smaller elements to be at the front of the queue, two ways are listed below
|
||||||
|
|
||||||
|
1. Overload the (`<`) operator to output the opposite effect.
|
||||||
|
|
||||||
|
2. Overload the (`>`) operator properly and use the (`greater<T>`) functor.
|
||||||
|
|
||||||
|
</Warning>
|
||||||
|
|
|
@ -24,23 +24,29 @@ export const metadata = {
|
||||||
new Problem("POI", "Mafia", "https://szkopul.edu.pl/problemset/problem/w3YAoAT3ej27YeiaNWjK57_G/site/?key=statement", "Hard", false, ["Func Graph"], ""),
|
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", "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, [], ""),
|
new Problem("POI", "Frog", "https://szkopul.edu.pl/problemset/problem/qDH9CkBHZKHY4vbKRBlXPrA7/site/?key=statement", "Hard", false, [], ""),
|
||||||
|
new Problem("ojuz", "Space Pirate", "JOI14_space_pirate", "Very Hard", false, ["Graphs"], "One of the most difficult problems of all time. Build a tree with a single back edge. Break into three cases: path -> other cycle, path -> subtree, path -> non-subtree. Then perform some black magic."),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
## Functional Graphs
|
||||||
|
|
||||||
We'll consider graphs like the one presented in this problem:
|
We'll consider graphs like the one presented in this problem:
|
||||||
|
|
||||||
<Problems problems={metadata.problems.sample} />
|
<Problems problems={metadata.problems.sample} />
|
||||||
|
|
||||||
< br/>
|
< br/>
|
||||||
|
|
||||||
Aka **successor graph**.
|
In a **functional graph**, each node has exactly one out-edge.
|
||||||
|
This is also commonly referred to as a **successor graph**.
|
||||||
|
|
||||||
|
### Resources
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
<Resource source="CPH" title="16.3, 16.4 - Successor Graphs"></Resource>
|
<Resource source="CPH" title="16.3, 16.4 - Successor Graphs"></Resource>
|
||||||
</Resources>
|
</Resources>
|
||||||
|
|
||||||
## Implementation
|
### 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.
|
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.
|
||||||
|
|
||||||
|
@ -82,6 +88,14 @@ int main()
|
||||||
|
|
||||||
**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)
|
**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)
|
||||||
|
|
||||||
|
### Resources
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
### Implementation
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
//UNTESTED
|
//UNTESTED
|
||||||
pair<int, int> detect_cycle(int *next, int start_node) //return pair(length of cycle, distance from start node to in cycle)
|
pair<int, int> detect_cycle(int *next, int start_node) //return pair(length of cycle, distance from start node to in cycle)
|
||||||
|
@ -105,12 +119,7 @@ pair<int, int> detect_cycle(int *next, int start_node) //return pair(length of c
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<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 problems={metadata.problems.general} />
|
<Problems problems={metadata.problems.general} />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
id: centroid
|
id: centroid
|
||||||
title: "Centroid Decomposition"
|
title: "Centroid Decomposition"
|
||||||
author: Benjamin Qi
|
author: Benjamin Qi, Siyong Huang
|
||||||
prerequisites:
|
prerequisites:
|
||||||
- dfs
|
- dfs
|
||||||
- SRQ
|
- SRQ
|
||||||
|
@ -14,12 +14,12 @@ import { Problem } from "../models";
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
problems: {
|
problems: {
|
||||||
general: [
|
general: [
|
||||||
new Problem("CF", "Ciel the Commander", "problemset/problem/321/C", "Easy", false, ["Centroid"]),
|
new Problem("CF", "Ciel the Commander", "problemset/problem/321/C", "Easy", false, ["Centroid"], ""),
|
||||||
new Problem("CF", "Sherlock's bet to Moriarty", "contest/776/problem/F", "Normal", false, ["Centroid"], ""),
|
new Problem("CF", "Sherlock's bet to Moriarty", "contest/776/problem/F", "Normal", false, ["Centroid"], ""),
|
||||||
new Problem("CF", "Digit Tree", "contest/715/problem/C", "Normal", false, ["Centroid", "NT"], ""),
|
new Problem("CF", "Digit Tree", "contest/715/problem/C", "Normal", false, ["Centroid", "NT"], ""),
|
||||||
new Problem("CF", "Double Tree", "contest/1140/problem/G", "Normal", false, ["Centroid", "DP"], ""),
|
new Problem("CF", "Double Tree", "contest/1140/problem/G", "Normal", false, ["Centroid", "DP"], ""),
|
||||||
new Problem("ojuz", "JOI - Factories", "JOI14_factories", "Normal", false, ["Centroid"], ""),
|
new Problem("ojuz", "JOI - Factories", "JOI14_factories", "Normal", false, ["Centroid"], ""),
|
||||||
new Problem("CF", "Sum of Prefix Sums", contest/1303/problem/G", "Hard", false, ["Centroid", "CHT"], ""),
|
new Problem("CF", "Sum of Prefix Sums", "contest/1303/problem/G", "Hard", false, ["Centroid", "CHT"], ""),
|
||||||
new Problem("YS", "Frequency Table of Tree Distance", "frequency_table_of_tree_distance", "Hard", false, ["Centroid", "FFT"], ""),
|
new Problem("YS", "Frequency Table of Tree Distance", "frequency_table_of_tree_distance", "Hard", false, ["Centroid", "FFT"], ""),
|
||||||
new Problem("DMOJ", "Bob Equilibrium", "dmopc19c7p6", "Hard", false, ["Centroid"], "tight time limit"),
|
new Problem("DMOJ", "Bob Equilibrium", "dmopc19c7p6", "Hard", false, ["Centroid"], "tight time limit"),
|
||||||
new Problem("DMOJ", "Time Traveller Imaxblue", "tc19summerh", "Hard", false, ["Centroid"], ""),
|
new Problem("DMOJ", "Time Traveller Imaxblue", "tc19summerh", "Hard", false, ["Centroid"], ""),
|
||||||
|
@ -29,6 +29,12 @@ export const metadata = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
## Centroid Decomposition
|
||||||
|
|
||||||
|
**Centroid Decomposition** is a divide and conquer technique for trees.
|
||||||
|
The **centroid** of a tree is a node which, if rooted, results in no other nodes having a subtree of size greater than $\frac{N}{2}$.
|
||||||
|
**Centroid Decomposition** works by repeated splitting the tree and each of the resulting subgraphs at the centroid, producing $O(\log N)$ layers of subgraphs.
|
||||||
|
|
||||||
### Tutorial
|
### Tutorial
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
|
@ -36,6 +42,54 @@ export const metadata = {
|
||||||
<Resource source="GFG" title="Centroid Decomposition of Tree" url="centroid-decomposition-of-tree"></Resource>
|
<Resource source="GFG" title="Centroid Decomposition of Tree" url="centroid-decomposition-of-tree"></Resource>
|
||||||
</Resources>
|
</Resources>
|
||||||
|
|
||||||
|
### Implementation
|
||||||
|
|
||||||
|
<LanguageSection>
|
||||||
|
|
||||||
|
<CPPSection>
|
||||||
|
|
||||||
|
<!-- pulled from https://codeforces.com/contest/1303/submission/76216413, which I think is my most recent centroid problem -->
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool r[MN];//removed
|
||||||
|
int s[MN];//subtree size
|
||||||
|
int dfs(int n, int p = 0)
|
||||||
|
{
|
||||||
|
s[n] = 1;
|
||||||
|
for(int x : a[n])
|
||||||
|
if(x != p && !r[x])
|
||||||
|
s[n] += dfs(x, n);
|
||||||
|
return s[n];
|
||||||
|
}
|
||||||
|
int get_centroid(int n, int ms, int p = 0)//n = node, ms = size of tree, p = parent
|
||||||
|
{
|
||||||
|
for(int x : a[n])
|
||||||
|
if(x != p && !r[x])
|
||||||
|
if(s[x]*2 > ms)
|
||||||
|
return get_centroid(x, ms, n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
void centroid(int n = 1)
|
||||||
|
{
|
||||||
|
int C = get_centroid(n, dfs(n));
|
||||||
|
|
||||||
|
//do something
|
||||||
|
|
||||||
|
r[C] = 1;
|
||||||
|
for(int x : a[C])
|
||||||
|
if(!r[x])
|
||||||
|
centroid(x);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</CPPSection>
|
||||||
|
|
||||||
|
<JavaSection />
|
||||||
|
|
||||||
|
<PySection />
|
||||||
|
|
||||||
|
</LanguageSection>
|
||||||
|
|
||||||
### Problems
|
### Problems
|
||||||
|
|
||||||
<Problems problems={metadata.problems.general} />
|
<Problems problems={metadata.problems.general} />
|
||||||
|
|
Reference in a new issue