diff --git a/src/Graph/Graph.md b/src/Graph/Graph.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/Graph/Tree/Diameter/diameter.cpp b/src/Graph/Tree/Diameter/diameter.cpp new file mode 100644 index 000000000..4cadb8c98 --- /dev/null +++ b/src/Graph/Tree/Diameter/diameter.cpp @@ -0,0 +1,46 @@ +#include +#include +#include + +using namespace std; + +vector> tree ; +vector visited, toLeaf, path_length; + +void dfs(int node){ + visited[node] = true; + vector length = {-1}; + for(int child : tree[node]){ + if(visited[child]) + continue; + dfs(child); + toLeaf[node] = max(toLeaf[node], 1 + toLeaf[child]); + length.push_back(toLeaf[child]); + } + int n = length.size(), m = min((int)length.size(),2); + for(int i = 0; i < m; i++){ + for(int j = i+1; j < n; j++){ + if(length[i] < length[j]) + swap(length[i], length[j]); + } + path_length[node] += length[i] + 1; + } +} + +int main(){ + int n; + cin >> n; + int m = n - 1; + tree.resize(n+1), toLeaf.resize(n+1,0), path_length.resize(n+1,0), visited.resize(n+1,false); + while(m--){ + int x, y; + cin >> x >> y; + tree[x].push_back(y); + tree[y].push_back(x); + } + int root = 1; + dfs(root); + int diameter = *max_element(path_length.begin(), path_length.end()); + cout << diameter << "\n"; + return 0; +} \ No newline at end of file diff --git a/src/Graph/Tree/Diameter/diameter.md b/src/Graph/Tree/Diameter/diameter.md new file mode 100644 index 000000000..a71c1e0eb --- /dev/null +++ b/src/Graph/Tree/Diameter/diameter.md @@ -0,0 +1,97 @@ +## **Diameter of a tree** +The Diameter of tree is the *maximum* length between two nodes. For example :
+Consider the following tree of 7 nodes + +
+ +

+ +Here, *Diameter* = 4 . + +## **Algorithm** + +First, root the tree arbitarily. +
+ +

+ +For each *node*, we calculate *toLeaf(node)* which denotes +*maximum* length of a path from the *node* to any *leaf*.
+ +``` +if node is leaf : + toLeaf[node] = 0 +else + toLeaf[node] = 1 + max(toLeaf[child]) | for all child of node +``` + +
+ +We can use DFS to calculate *toLeaf(node)*.
+```cpp +vector toLeaf(n+1, 0); // n is no. of nodes +void dfs(int node){ + visited[node] = true; + for(int child : tree[node]){ + if(visited[child]) + continue; + dfs(child); + toLeaf[node] = max(toLeaf[node], 1 + toLeaf[child]); + } +} +``` +
+
+ +

+ + + +Now calculate *path_length(node)* which denotes *maximum* length of a path whose highest point is node. + +``` +if node is leaf : + path_length[node] = 0 +else if node has only 1 child : + path_length[node] = toLeaf[child] + 1 +else + Take two distinct child a,b such that (toLeaf[a] + toLeaf[b]) is maximum, then + path_length[node] = (toLeaf[a] + 1) + (toLeaf[b] + 1) + +``` +Here is the implementation . +```cpp +vector toLeaf(n+1, 0), path_length(n+1, 0); +void dfs(int node){ + visited[node] = true; + vector length = {-1}; // allows us to handle the cases when node has less than 2 children + for(int child : tree[node]){ + if(visited[child]) + continue; + dfs(child); + toLeaf[node] = max(toLeaf[node], 1 + toLeaf[child]); + length.push_back(toLeaf[child]); + } + int s = length.size(), m = min((int)length.size(),2); + for(int i = 0; i < m; i++){ + for(int j = i+1; j < s; j++){ + if(length[i] < length[j]) + swap(length[i], length[j]); + } + path_length[node] += length[i] + 1; + } +} +``` + +
+
+ +

+ +Finally, *Diameter = maximum* of all lengths in path_length. Therefore here, *Diameter* = 4. + +## *Problems* +- [Tree Diameter](https://cses.fi/problemset/task/1131/) +## *Reference* +- Competitive Programmer's Handbook by Antii Laaksonen. + diff --git a/src/Graph/Tree/Tree.md b/src/Graph/Tree/Tree.md new file mode 100644 index 000000000..cb641087d --- /dev/null +++ b/src/Graph/Tree/Tree.md @@ -0,0 +1,9 @@ +## **Tree** + +We can define *Tree* as a connected undirected graph with *no cycles* . + +There are some more ways we can define Tree . Here are some equivalent definitions : + +- connected undirected graph with N nodes and N-1 edges. +- connected undirected graph with only unique paths i.e there is one and only path from one node to another. +- connected undirected graph where if you remove 1 edge it no longer remains connected. \ No newline at end of file diff --git a/src/SUMMARY.md b/src/SUMMARY.md index af68fc36f..1255e7649 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -3,5 +3,7 @@ - [Introduction](./introduction.md) - [Persistent Data Structure](./PersistentDS/README.md) - [Persistent Segment Trees](./PersistentDS/persistentST.md) - - \ No newline at end of file +- [Graph](./Graph/Graph.md) + - [Tree](./Graph/Tree/Tree.md) + - [Diameter](./Graph/Tree/Diameter/diameter.md) +