├── FLOW ├── images │ ├── a.md │ ├── 1.png │ ├── 10.png │ ├── 11.jpg │ ├── 12.jpg │ ├── 13.jpg │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ ├── 9.png │ ├── konigs_1.png │ ├── konigs_2.png │ ├── konigs_3.png │ ├── konigs_4.png │ ├── vertex_cover1.png │ ├── vertex_cover2.png │ ├── vertex_cover3.png │ ├── independent_set1.png │ ├── independent_set2.png │ ├── independent_set3.png │ ├── independent_set4.png │ ├── vertex_cover3_235.jpg │ ├── vertex_cover3_1234.jpg │ ├── vertex_cover3_1245.jpg │ ├── Independent_bipartite1.png │ ├── Independent_bipartite2.png │ └── Independent_bipartite3.png ├── Max Flow (Ford-Fulkerson) O(E * max flow).cpp ├── Max Flow (for general use) (Dinic's algorithm) O(V^2 * E).cpp ├── Max Flow (Edmonds-Karp) O(V * E^2).cpp ├── Minimum Cost Maximum Flow With Negative Cycle(MCMF).cpp ├── Minimum Cut.cpp └── README.md ├── GRAPH ├── README.md ├── Articulartion Points .cpp ├── Articulation Bridge .cpp ├── Topological Sorting .cpp ├── Dijkstra .cpp ├── Why Dijkstra Fails For Negative Edges.md ├── Negative Cycle Printing .cpp ├── MST Krushkal .cpp ├── MST Prims .cpp ├── Bellman Ford .cpp ├── Shortest Path In A DAG O(V+E) .cpp ├── Cycle Printing in Directed Graph .cpp ├── Strongly Connected Components to DAG.cpp ├── Longest Path In A DAG O(V+E).cpp ├── Bi-connected Components.cpp ├── DSU Modified(DSU+Ordered Set).cpp ├── 2 - SAT with solution .cpp ├── Johnson’s algorithm for All-pairs shortest paths.cpp └── Euler Path_Circuit.cpp ├── GAME THEORY ├── README.md └── Game Theory ( MEX , Sprague-Grundy Number Calculation).cpp ├── TECHNIQUES ├── README.md ├── Inclusion Exclusion .cpp └── Sliding Window (Fixed,Variable Length Window Template).cpp ├── TREE ALGOs ├── README.md ├── Centroid Decomposition │ ├── 1.jpeg │ └── 2.jpeg ├── LCA with Binary lifting.cpp ├── Binary Lifting (Sum Query between two vertex of a tree) .cpp ├── LCA in O(1).cpp ├── Euler Tour Improved (FOR USE).cpp └── Heavy Light Decomposition + Iterative Segment Tree.cpp ├── DATA STRUCTURES ├── README.md ├── GP Hash .cpp ├── MO's Algorithm (K-th Minimum in Range).cpp ├── Order Multiset Template.cpp ├── Trie .cpp ├── Merge Sort Tree (k-th minimum in range) .cpp ├── Segment Tree With Lazy Propagation.cpp ├── Persistent Segment Tree (k-th minimum in range).cpp ├── DSU Modified(DSU+Ordered Set).cpp ├── Trie Xor (Min - Max).cpp └── Wavelet Tree.cpp ├── STRINGS ├── README.md ├── caesar cipher.cpp ├── Z Function.cpp ├── Randomized Hashing (Mapping each element) (Multiset Query).cpp ├── KMP.cpp ├── Trie .cpp ├── Manacher Algorithm (Palindromic Substring).cpp ├── Aho Corasick.cpp └── Trie Xor (Min - Max).cpp ├── MATH ├── README.md ├── Prime Factorization .cpp ├── Matrix Exponentiation .cpp ├── Pollard Rho ( probabilistic Factorization) Algorithm.cpp └── Gaussian Elimination.cpp ├── README.md └── DP ├── Linear DP ├── LIS DP (longest increasing sub sequence).cpp ├── README.md └── Coin Change DP all variants.cpp ├── KnapSack DP └── README.md └── README.md /FLOW/images/a.md: -------------------------------------------------------------------------------- 1 | fr 2 | -------------------------------------------------------------------------------- /GRAPH/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /GAME THEORY/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /TECHNIQUES/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /TREE ALGOs/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DATA STRUCTURES/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /STRINGS/README.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | -------------------------------------------------------------------------------- /MATH/README.md: -------------------------------------------------------------------------------- 1 | # Include all Sieve Variant 2 | -------------------------------------------------------------------------------- /FLOW/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/1.png -------------------------------------------------------------------------------- /FLOW/images/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/10.png -------------------------------------------------------------------------------- /FLOW/images/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/11.jpg -------------------------------------------------------------------------------- /FLOW/images/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/12.jpg -------------------------------------------------------------------------------- /FLOW/images/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/13.jpg -------------------------------------------------------------------------------- /FLOW/images/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/14.jpg -------------------------------------------------------------------------------- /FLOW/images/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/15.jpg -------------------------------------------------------------------------------- /FLOW/images/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/16.jpg -------------------------------------------------------------------------------- /FLOW/images/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/17.jpg -------------------------------------------------------------------------------- /FLOW/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/2.png -------------------------------------------------------------------------------- /FLOW/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/3.png -------------------------------------------------------------------------------- /FLOW/images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/4.png -------------------------------------------------------------------------------- /FLOW/images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/5.png -------------------------------------------------------------------------------- /FLOW/images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/6.png -------------------------------------------------------------------------------- /FLOW/images/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/7.png -------------------------------------------------------------------------------- /FLOW/images/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/8.png -------------------------------------------------------------------------------- /FLOW/images/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/9.png -------------------------------------------------------------------------------- /FLOW/images/konigs_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/konigs_1.png -------------------------------------------------------------------------------- /FLOW/images/konigs_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/konigs_2.png -------------------------------------------------------------------------------- /FLOW/images/konigs_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/konigs_3.png -------------------------------------------------------------------------------- /FLOW/images/konigs_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/konigs_4.png -------------------------------------------------------------------------------- /FLOW/images/vertex_cover1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/vertex_cover1.png -------------------------------------------------------------------------------- /FLOW/images/vertex_cover2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/vertex_cover2.png -------------------------------------------------------------------------------- /FLOW/images/vertex_cover3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/vertex_cover3.png -------------------------------------------------------------------------------- /FLOW/images/independent_set1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/independent_set1.png -------------------------------------------------------------------------------- /FLOW/images/independent_set2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/independent_set2.png -------------------------------------------------------------------------------- /FLOW/images/independent_set3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/independent_set3.png -------------------------------------------------------------------------------- /FLOW/images/independent_set4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/independent_set4.png -------------------------------------------------------------------------------- /FLOW/images/vertex_cover3_235.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/vertex_cover3_235.jpg -------------------------------------------------------------------------------- /FLOW/images/vertex_cover3_1234.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/vertex_cover3_1234.jpg -------------------------------------------------------------------------------- /FLOW/images/vertex_cover3_1245.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/vertex_cover3_1245.jpg -------------------------------------------------------------------------------- /FLOW/images/Independent_bipartite1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/Independent_bipartite1.png -------------------------------------------------------------------------------- /FLOW/images/Independent_bipartite2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/Independent_bipartite2.png -------------------------------------------------------------------------------- /FLOW/images/Independent_bipartite3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/FLOW/images/Independent_bipartite3.png -------------------------------------------------------------------------------- /TREE ALGOs/Centroid Decomposition/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/TREE ALGOs/Centroid Decomposition/1.jpeg -------------------------------------------------------------------------------- /TREE ALGOs/Centroid Decomposition/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArfatulAsif/Competitive-Programming-TopicWise/HEAD/TREE ALGOs/Centroid Decomposition/2.jpeg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Competitive-Programming-TopicWise-Personal-Notes 2 | In this repository I have stored templates and my personal notes for competitive programming topics like DP,Greedy,Graph,Math. 3 | -------------------------------------------------------------------------------- /DP/Linear DP/LIS DP (longest increasing sub sequence).cpp: -------------------------------------------------------------------------------- 1 | // Intermediary 2 | // Young kid on the block 3 | // AIAsif try's Continuing the journey 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace __gnu_pbds; 9 | #define endl "\n" 10 | #define inf 1000000000000000000 11 | #define int long long int 12 | #define ordered_set tree, rb_tree_tag, tree_order_statistics_node_update> 13 | 14 | const int N = 1e6; 15 | int dp[N]; 16 | vectornums; 17 | int n; 18 | 19 | int32_t main() 20 | { 21 | ios::sync_with_stdio(0); 22 | cin.tie(0); 23 | 24 | 25 | 26 | dp[0] = 1; 27 | 28 | for (int i = 1; i < n; i++) 29 | { 30 | for (int j = 0; j < i; j++) 31 | { 32 | if (nums[i] > nums[j]) 33 | { 34 | dp[i] = max(dp[i], dp[j] + 1); 35 | } 36 | } 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /STRINGS/caesar cipher.cpp: -------------------------------------------------------------------------------- 1 | // Author: (AIA) Registration : 17 2 | 3 | string secret_code = "Here the Algorithm is caesar cipher, uses a secret key techniques like the one in jwt token."; 4 | 5 | 6 | int helper(string key) 7 | { 8 | // implement this method as you want it. 9 | } 10 | 11 | 12 | char encryt(char ch, string code) 13 | { 14 | int key = helper(code); 15 | 16 | 17 | int res_c = ( ch + key) % 128; 18 | 19 | return (char) res_c; 20 | } 21 | 22 | char decrypt(char ch, string code) 23 | { 24 | int key = helper(code); 25 | 26 | 27 | int res_c = ((ch-key) % 128 + 128 ) % 128; 28 | 29 | return (char) res_c; 30 | } 31 | 32 | 33 | 34 | 35 | string encrypted_string(string str) 36 | { 37 | for(int i=0;i z_function(const string &s) 10 | { 11 | int n = s.size(); 12 | vectorz(n); 13 | int l = 0; 14 | int r = 0; 15 | for(int i=1;ir) 26 | { 27 | l = i; 28 | r = i+z[i]; 29 | } 30 | } 31 | 32 | return z; 33 | } 34 | 35 | 36 | int stringCompression(const string &s) //length of smallest string t such s = t+t+..+t ; Or s is the concatenation of one or more t; 37 | { 38 | vectorz = z_function(s); 39 | 40 | for(int i=1;ifact(int n) 34 | { 35 | mapm; 36 | 37 | while(n>1) 38 | { 39 | int a = lp[n]; 40 | m[a]++; 41 | n/=lp[n]; 42 | } 43 | if(n>1) 44 | { 45 | m[n]++; 46 | } 47 | 48 | return m; 49 | 50 | } 51 | 52 | 53 | int32_t main() 54 | { 55 | 56 | pre(); // Remember to declare this in the main function 57 | 58 | 59 | int n; 60 | cin>>n; 61 | 62 | mapm; 63 | m = fact(n); 64 | 65 | for(auto x: m) 66 | { 67 | cout<graph[N]; 4 | bool vis[N]; 5 | vectorparent(N,-1); 6 | int dis[N]; 7 | int low[N]; 8 | setAP; 9 | 10 | void dfs(int s , int time = 0) 11 | { 12 | time++; 13 | vis[s] = true; 14 | dis[s] = low[s] = time; 15 | int childno = 0; 16 | for(auto child : graph[s]) 17 | { 18 | if(parent[s]==child) 19 | { 20 | continue; 21 | } 22 | if(vis[child]) 23 | { 24 | low[s] = min(low[s],dis[child]); 25 | continue; 26 | } 27 | childno++; 28 | parent[child] = s; 29 | dfs(child, time); 30 | low[s] = min(low[s],low[child]); 31 | 32 | if(parent[s]!=-1 && dis[s]<=low[child]) // make sure s is not the root 33 | { 34 | AP.insert(s); 35 | } 36 | } 37 | if(s==0 && childno>1) // handling the root case 38 | { 39 | AP.insert(s); 40 | } 41 | 42 | return; 43 | } 44 | 45 | 46 | int32_t main() 47 | { 48 | ios::sync_with_stdio(0); 49 | cin.tie(0); 50 | int n,m; 51 | cin>>n>>m; 52 | for(int i=0;i>x>>y; 56 | graph[x].push_back(y); 57 | graph[y].push_back(x); 58 | } 59 | dfs(0); 60 | for(auto x : AP) 61 | { 62 | cout<graph[N]; 4 | bool vis[N]; 5 | vectorparent(N,-1); 6 | int dis[N]; 7 | int low[N]; 8 | set>bridge; 9 | 10 | void dfs(int s , int time = 0) 11 | { 12 | time++; 13 | vis[s] = true; 14 | dis[s] = low[s] = time; 15 | for(auto child : graph[s]) 16 | { 17 | if(parent[s]==child) 18 | { 19 | continue; 20 | } 21 | if(vis[child]) 22 | { 23 | low[s] = min(low[s],dis[child]); // backedge checking 24 | continue; 25 | } 26 | parent[child] = s; 27 | dfs(child, time); 28 | low[s] = min(low[s],low[child]); 29 | 30 | if(dis[s]>n>>m; 46 | for(int i=0;i>x>>y; 50 | graph[x].push_back(y); 51 | graph[y].push_back(x); 52 | } 53 | for(int i=0;i> 30)) * 0xbf58476d1ce4e5b9; 9 | x = (x ^ (x >> 27)) * 0x94d049bb133111eb; 10 | return x ^ (x >> 31); 11 | } 12 | 13 | size_t operator()(uint64_t x) const { 14 | static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); 15 | return splitmix64(x + FIXED_RANDOM); 16 | } 17 | }; //For long long int to long long int 18 | 19 | 20 | typedef gp_hash_tabletable; 21 | 22 | 23 | 24 | 25 | 26 | 27 | // 28 | //struct chash { 29 | // int operator()(pair x) const { return x.first* 31 + x.second; } 30 | //}; 31 | //gp_hash_table, int, chash> table; 32 | 33 | 34 | //This was for {pair to int} mapping 35 | 36 | 37 | int32_t main() 38 | { 39 | ios::sync_with_stdio(0); 40 | cin.tie(0); 41 | 42 | //gp_hash_table m; can do this too 43 | 44 | table m; 45 | 46 | 47 | m[1]++; 48 | m[2]++; 49 | m[1]++; 50 | m[1]++; 51 | 52 | cout<graph[N]; 6 | bool vis[N]; 7 | int in[N]; 8 | 9 | int32_t main() 10 | { 11 | ios::sync_with_stdio(0); 12 | cin.tie(0); 13 | 14 | int n,m; 15 | cin>>n>>m; 16 | 17 | for(int i=0;i>x>>y; 21 | graph[x].push_back(y); 22 | in[y]++; 23 | } 24 | queueq; 25 | for(int i=1;i<=n;i++) 26 | { 27 | if(in[i]==0) 28 | { 29 | q.push(i); 30 | } 31 | } 32 | vectorans; 33 | while(!q.empty()) 34 | { 35 | int father = q.front(); 36 | vis[father] = true; 37 | ans.push_back(father); 38 | q.pop(); 39 | for(auto child : graph[father]) 40 | { 41 | if(vis[child]) 42 | { 43 | continue; 44 | } 45 | in[child]--; 46 | if(in[child]==0) 47 | { 48 | q.push(child); 49 | vis[child] = true; 50 | } 51 | } 52 | } 53 | 54 | 55 | for(int i=1;i<=n;i++) 56 | { 57 | if(vis[i]==false) 58 | { 59 | cout<<"IMPOSSIBLE"<>Multiply (vector> &one , vector> &two) //pass them as reference to save time 5 | { 6 | vector>res; 7 | int D = one.size(); 8 | for(int i=0;itemp; 11 | for(int j=0;j> Mat_Ex(vector> Mat , int b) //don't pass Mat as reference 30 | { 31 | vector> ans 32 | { 33 | {1,0}, 34 | {0,1} 35 | }; //Identity Matrix {Adjust its dimension according to Mat 36 | 37 | while(b>0) 38 | { 39 | if(b&1) 40 | { 41 | ans = Multiply(ans,Mat); 42 | } 43 | Mat = Multiply(Mat,Mat); 44 | b>>=1; 45 | } 46 | 47 | return ans; 48 | 49 | } 50 | 51 | int32_t main() 52 | { 53 | ios::sync_with_stdio(0); 54 | cin.tie(0); 55 | 56 | // For finding nth fibbonacci 57 | vector>Mat{ 58 | {1,1}, 59 | {1,0} 60 | }; 61 | 62 | int n; 63 | 64 | cin>>n; //n>2 65 | 66 | cout<>n>>q; 28 | 29 | vectorv1,v2; 30 | 31 | for(int i=0;i>a; 35 | v1.push_back(a); 36 | } 37 | 38 | for(int i=0;i>a; 42 | v2.push_back(a); 43 | } 44 | 45 | mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); 46 | 47 | vector Hash(N); 48 | 49 | for (int i = 0; i < N; i++) 50 | { 51 | Hash[i] = uniform_int_distribution(1, Mod-1)(rng); 52 | 53 | } 54 | 55 | for(int i=0;i>l1>>r1>>l2>>r2; 67 | 68 | int take1 = (H1[r1] - H1[l1-1] + Mod)%Mod; 69 | 70 | int take2 = (H2[r2] - H2[l2-1] + Mod)%Mod; 71 | 72 | 73 | if(take1 == take2) 74 | { 75 | cout<<"Yes"<>graph[N]; 4 | const int inf = 1e18; 5 | bool vis[N]; 6 | int dist[N]; 7 | 8 | 9 | void dijkstra(int ss) 10 | { 11 | dist[ss] = 0; 12 | priority_queue , vector> , greater> >pq; 13 | pq.push({0,ss}); 14 | 15 | while(!pq.empty()) 16 | { 17 | 18 | int father = pq.top().second; 19 | 20 | pq.pop(); 21 | 22 | 23 | //This line is very important for time saving 24 | if(vis[father]) 25 | { 26 | 27 | continue; 28 | } 29 | 30 | vis[father] = true; 31 | 32 | 33 | for(auto child : graph[father]) 34 | { 35 | int v = child.first; 36 | int vw = child.second; 37 | if(vis[v]) 38 | { 39 | continue; 40 | } 41 | if(dist[v]>dist[father]+vw) 42 | { 43 | dist[v] = dist[father]+vw; 44 | pq.push({dist[v] , v}); 45 | } 46 | } 47 | } 48 | 49 | 50 | } 51 | 52 | int32_t main() 53 | { 54 | ios::sync_with_stdio(0); 55 | cin.tie(0); 56 | int n,m; 57 | cin>>n>>m; 58 | 59 | for(int i=0;i>x>>y>>w; 63 | graph[x].push_back({y,w}); 64 | } 65 | for(int i=0;i 2 ----------> 3 18 | \ / 19 | \ 4 1 / 20 | \ / 21 | \ / 22 | \> 4 2), dist[3] = 2 (1 -> 2 -> 3), dist[4] = 3 (1 -> 2 -> 3 -> 4). 26 | 27 | **If we increase weight of all edges by a constant value, lets say 1, will the relative distance (include edges) remained same?** 28 | 29 | ``` 30 | 2 2 31 | 1 -----------> 2 ----------> 3 32 | \ / 33 | \ 5 2 / 34 | \ / 35 | \ / 36 | \> 4 2), dist[3] = 4 (1 -> 2 -> 3), dist[4] = 5 (1 -> 4). 40 | **Look dist[4] has changed its relative order** 41 | 42 | 43 | 44 | 45 | ## Reweight each edges of the graph like w'(u, v) = w(u, v) + potential[u] – potential[v], using Bellman-Ford to eliminate negative weights, then apply Dijkstra's algorithm to find the shortest paths from source to all other vertex. 46 | 47 | **It will works: The question is where we can use it?** 48 | **Answer: Jonson's algorithm for all pair shortest path** 49 | 50 | ## Jonson's algorithm for all pair shortest path: 51 | **Step 1: Adjust negative edges using bellman-ford.** 52 | **Step 2: Run dijkstra for each vertex to find all pair shortest path** 53 | 54 | ``` 55 | This is better than floyed-warshall O(V^3). As it's complexity is O(V2log V + VE) 56 | ``` 57 | 58 | 59 | 60 | # By the way, it will not work if negative cycle exists. 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /MATH/Pollard Rho ( probabilistic Factorization) Algorithm.cpp: -------------------------------------------------------------------------------- 1 | 2 | //This is an algorithm For Finding a Divisor of a Number . It is a probabilistic algorithm . 3 | //Using BirthDay paradox to explain the probability 4 | 5 | //And its is a good algorthm for finding a divisior of a Large Number such as N >= 1e15 [ which requres less than 1e6 moves ] 6 | [There is a 90% plus probability that using 1e6 Random number we shall get a divisor] 7 | 8 | 9 | int cnt = 0; 10 | int Pollard_Rho(int N) 11 | { 12 | if(N==1) 13 | { 14 | return N; 15 | } 16 | if(N%2==0) 17 | { 18 | return 2; 19 | } 20 | 21 | srand(time(NULL)); 22 | 23 | int x = (rand()%(N-2))+2; 24 | 25 | int y = x; 26 | 27 | int d = 1; 28 | 29 | int c = (rand()%(N-1))+1; 30 | 31 | while(d==1) 32 | { 33 | //Tortoise : Slow pointer 34 | x = (((x%N)*(x%N))%N + c)%N; 35 | 36 | //Hare : Fast Pointer 37 | y = (((y%N)*(y%N))%N + c)%N; 38 | y = (((y%N)*(y%N))%N + c)%N; 39 | 40 | d = __gcd( abs(x-y) , N); 41 | 42 | ++cnt; 43 | 44 | if(d==N) // x mod N = y mod N . which means [ abs(x-y) = N ] eta hole Notun kore abar algorithm chalate hobe 45 | { 46 | //Mane Pollard rho loop e pore gese 47 | 48 | //Notun iteration dorkar hobe 49 | return Pollard_Rho(N); 50 | } 51 | 52 | 53 | } 54 | 55 | return d; 56 | } 57 | 58 | int32_t main() 59 | { 60 | ios::sync_with_stdio(0); 61 | cin.tie(0); 62 | 63 | 64 | int N = 223007; 65 | 66 | N = N*N*N; 67 | //cin>>N; 68 | 69 | int d = Pollard_Rho(N); 70 | 71 | cout<<"The Number : "< 8 | #include 9 | #include 10 | using namespace std; 11 | using namespace __gnu_pbds; 12 | #define endl "\n" 13 | #define int long long int 14 | #define ordered_set tree< int, null_type, less, rb_tree_tag,tree_order_statistics_node_update> 15 | 16 | const int N = 1e4+100; 17 | int dp[N]; 18 | int calculateMex(unordered_set &s) 19 | { 20 | int mex = 0; 21 | while(s.find(mex)!=s.end()) 22 | { 23 | mex++; 24 | } 25 | return mex; 26 | } 27 | 28 | int grundy(int n) //depending on the problem this function can be very different ....... Look at the light oj various Sprague-Grundy Number problems 29 | { 30 | if(n<3) 31 | { 32 | dp[n] = 0; 33 | return 0; 34 | } 35 | if(dp[n]!=-1) 36 | { 37 | return dp[n]; 38 | } 39 | 40 | int left = n/2; 41 | 42 | if(n%2==0) 43 | { 44 | left--; 45 | } 46 | 47 | unordered_sets; 48 | 49 | for(int i=1;i<=left;i++) 50 | { 51 | s.insert(grundy(i)^grundy(n-i)); 52 | } 53 | 54 | dp[n] = calculateMex(s); 55 | 56 | return dp[n]; 57 | } 58 | 59 | int32_t main() 60 | { 61 | ios::sync_with_stdio(0); 62 | cin.tie(0); 63 | 64 | int t; 65 | cin>>t; 66 | 67 | memset(dp,-1,sizeof(dp)); 68 | 69 | for(int tt=1;tt<=t;tt++) 70 | { 71 | int n; 72 | cin>>n; 73 | 74 | int Xor = 0; 75 | 76 | for(int i=0;i>a; 80 | 81 | Xor ^= grundy(a); 82 | } 83 | 84 | cout<<"Case "<>n>>m; 16 | vector>edges; 17 | 18 | for(int i=0;i>x>>y>>w; 22 | edges.push_back({x,y,w}); 23 | } 24 | int take; 25 | 26 | for(int i=1;idis[u]+w) 32 | { 33 | dis[v] = dis[u]+w; 34 | take = v; 35 | relaxtant[v] = u; 36 | } 37 | } 38 | } 39 | 40 | if(take==-1) 41 | { 42 | cout<<"NO"<ans; 62 | 63 | for(int u = v ; ; u = relaxtant[u]) 64 | { 65 | ans.push_back(u); 66 | if(u==v && ans.size()>1) 67 | { 68 | break; 69 | } 70 | } 71 | 72 | reverse(ans.begin(),ans.end()); 73 | 74 | for(auto x : ans) 75 | { 76 | cout<>>edge; 6 | vector , int>>MST; 7 | int mstCost = 0; 8 | 9 | 10 | void make(int v) 11 | { 12 | parent[v] = v; 13 | sz[v] = 1; 14 | } 15 | 16 | int find(int v) 17 | { 18 | if(v==parent[v]) 19 | { 20 | return v; 21 | } 22 | return parent[v] = find(parent[v]); 23 | } 24 | 25 | void Union(int a,int b) 26 | { 27 | a = find(a); 28 | b = find(b); 29 | if(a!=b) 30 | { 31 | if(sz[a]>n>>m; 63 | for(int i=0;i>x>>y>>w; 67 | edge.push_back({w , { x , y }}); 68 | } 69 | sort(edge.begin() , edge.end()); 70 | for(int i=1;i<=n;i++) // 1 based 71 | { 72 | make(i); 73 | } 74 | Krushkal(); 75 | 76 | cout<<"----------"<>graph[N]; 5 | vectorkey(N , inf); 6 | vectorparent(N,-1); 7 | int mstCost = 0; 8 | int vis[N]; 9 | 10 | void Prims(int s) 11 | { 12 | priority_queue< pair , vector> , greater> > pq; 13 | key[s] = 0; 14 | pq.push({0,s}); 15 | parent[s] = -1; 16 | while(!pq.empty()) 17 | { 18 | int father = pq.top().second; 19 | 20 | if(vis[father]==false) 21 | { 22 | mstCost += pq.top().first; 23 | vis[father] = true; 24 | } 25 | 26 | pq.pop(); 27 | for(auto child : graph[father]) 28 | { 29 | if(vis[child.first]) 30 | { 31 | continue; 32 | } 33 | if(child.second < key[child.first]) // Note e leka ase why , tar por oo fresh mind a 2,1 ta mST draw kore buja jay . Try the graph attach below 34 | { 35 | key[child.first] = child.second; 36 | parent[child.first] = father; 37 | pq.push({child.second , child.first}); 38 | } 39 | } 40 | } 41 | return; 42 | } 43 | 44 | int32_t main() 45 | { 46 | ios::sync_with_stdio(0); 47 | cin.tie(0); 48 | int n,m; 49 | cin>>n>>m; 50 | for(int i=0;i>x>>y>>w; 54 | graph[x].push_back({y,w}); 55 | graph[y].push_back({x,w}); 56 | } 57 | Prims(1); 58 | cout<<"------"<>n>>m; 18 | vectoredges; 19 | 20 | for(int i=0;i>x>>y>>w; 24 | edges.push_back({x,y,w}); 25 | } 26 | 27 | vectordis(n+1,inf); 28 | 29 | dis[0] = 0; 30 | dis[1] = 0; // distant of source is 0 . very important 31 | 32 | vectorpar(n+4,-1); 33 | 34 | bool neg_cycle = false; 35 | 36 | for(int i=0;ipath; 61 | // 62 | // int v = n; 63 | // 64 | // while(v!=-1) // path printing 65 | // { 66 | // path.push_back(v); 67 | // v = par[v]; 68 | // } 69 | // 70 | // reverse(path.begin() , path.end()); 71 | // 72 | // for(auto x : path) 73 | // { 74 | // cout<graph[N]; 5 | bool vis[N]; 6 | int din[N]; 7 | int dout[N]; 8 | int tin = 0; 9 | const int L = log2(N); 10 | int up[N][L+1]; 11 | 12 | void dfs(int s,int par) 13 | { 14 | vis[s] = true; 15 | din[s] = tin++; 16 | 17 | up[s][0] = par; 18 | 19 | for(int i=1;i<=L;i++) 20 | { 21 | up[s][i] = up[ up[s][i-1] ][i-1]; // Here is the binary lifting is occuring try for this graph ( 1->2 , 2->3 , 3->4 , 4->5,5->6,6->7,7->8,8->9,9->10) then s = 10 er jonno eta draw kore buja 22 | } 23 | 24 | 25 | for(auto child : graph[s]) 26 | { 27 | if(vis[child]) 28 | { 29 | continue; 30 | } 31 | dfs(child,s); 32 | } 33 | dout[s] = tin++; 34 | } 35 | 36 | bool is_ancestor(int u,int v) // u is ancestor of v 37 | { 38 | if(din[u]<=din[v] && dout[u]>=dout[v]) 39 | { 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | 46 | 47 | int lca(int u,int v) 48 | { 49 | if(is_ancestor(u,v)) 50 | { 51 | return u; 52 | } 53 | if(is_ancestor(v,u)) 54 | { 55 | return v; 56 | } 57 | for(int i=L;i>=0;i--) 58 | { 59 | if(!is_ancestor(up[u][i] ,v)) // ancestor na hole jump dissi [up[1][0] = 1 na hole ei part kaj korbe na] 60 | { 61 | u = up[u][i]; 62 | } 63 | } 64 | return up[u][0]; 65 | 66 | } 67 | 68 | 69 | int32_t main() 70 | { 71 | ios::sync_with_stdio(0); 72 | cin.tie(0); 73 | int n,m; 74 | cin>>n>>m; 75 | 76 | for(int i=0;i>x>>y; 80 | graph[x].push_back(y); 81 | graph[y].push_back(x); 82 | } 83 | 84 | dfs(1,1); // parent of 1 should be 1 i.e. up[1][0] = 1; 85 | 86 | int q; 87 | cin>>q; 88 | while(q--) 89 | { 90 | int u,v; 91 | cin>>u>>v; 92 | cout<>graph[N]; 8 | int in[N]; 9 | vectordis(N,inf); 10 | int parent[N]; 11 | 12 | int32_t main() 13 | { 14 | ios::sync_with_stdio(0); 15 | cin.tie(0); 16 | int n,m; 17 | cin>>n>>m; 18 | for(int i=0;i>x>>y>>w; 22 | graph[x].push_back({y,w}); 23 | in[y]++; 24 | } 25 | queueq; 26 | 27 | for(int i=1;i<=n;i++) 28 | { 29 | if(in[i]==0) 30 | { 31 | q.push(i); 32 | } 33 | } 34 | vectortopo; 35 | while(!q.empty()) 36 | { 37 | int father = q.front(); 38 | topo.push_back(father); 39 | q.pop(); 40 | 41 | 42 | for(auto child: graph[father]) 43 | { 44 | in[child.first]--; 45 | if(in[child.first]==0) 46 | { 47 | q.push(child.first); 48 | } 49 | } 50 | } 51 | 52 | dis[1] = 0; 53 | 54 | for(auto s : topo) 55 | { 56 | if(dis[s]!=inf) 57 | { 58 | for(auto child: graph[s]) 59 | { 60 | if(dis[child.first]>dis[s]+child.second) 61 | { 62 | parent[child.first] = s; 63 | dis[child.first] = dis[s]+child.second; 64 | } 65 | } 66 | } 67 | } 68 | 69 | 70 | 71 | if(dis[n]==inf) 72 | { 73 | cout<<"IMPOSSIBLE"<ans; 82 | 83 | while(v!=0) 84 | { 85 | ans.push_back(v); 86 | v = parent[v]; 87 | } 88 | reverse(ans.begin(),ans.end()); 89 | 90 | 91 | cout<<"dis[n] " <10000000 can't be used as array index . 19 | - For problems with `easy` state relations, use bottom-up DP [iterative] . For `harder` relations, use top-down DP [recursive] . 20 | 21 | ## Step 1: Define DP States 22 | 23 | - **Most of the knapsack dp problems are actually like Linear DP:** 24 | - `dp[i]` = Maximum value gained with 0 to at most `i-th` weight [bottom-up] 25 | - `dp[i]` = Maximum value gained with at most `i to 0-th` weight [top-down] 26 | 27 | - **If we have multiple state relations the use Multiple States:** 28 | - `dp[i][j]` = Maximum value taken with at most `j` weight from `i-th` index to `0-th` index [top-down] 29 | - `dp[i][j][k]` = Number of ways to make `(profit >= minProfit)` from `i to n` elements with `j profit` and `k people` [top-down] 30 | 31 | For problems with multiple states, top-down approach is preferred. 32 | 33 | ## Common Top-Down Approach 34 | 35 | ```cpp 36 | // Top down approach 37 | int dp[1000][1000]; 38 | int f(int W, int wt[], int val[], int index) { 39 | if (index < 0) 40 | return 0; 41 | if (dp[index][W] != -1) 42 | return dp[index][W]; 43 | 44 | if (wt[index] > W) { 45 | dp[index][W] = f(W, wt, val, index - 1); 46 | return dp[index][W]; 47 | } else { 48 | dp[index][W] = max(val[index] + f(W - wt[index], wt, val, index - 1), f(W, wt, val, index - 1)); 49 | return dp[index][W]; 50 | } 51 | } 52 | 53 | int main() { 54 | int profit[] = {60, 100, 120}; 55 | int weight[] = {10, 20, 30}; 56 | int W = 50; 57 | 58 | cout << f(W, weight, profit, n); 59 | } 60 | ``` 61 | 62 | ## Common Bottom-Up Approach 63 | 64 | ```cpp 65 | // dp[w] = maximum value till w weight 66 | for (int i = 0; i < n; ++i) { 67 | for (int w = W; w >= 0; --w) { 68 | if (w - wt[i] >= 0) { 69 | dp[w] = max(dp[w], val[i] + dp[w - wt[i]]); 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | ## Problem List 76 | 77 | [LeetCode Knapsack DP Problem List](https://leetcode.com/list/50vif4uc/) 78 | 79 | ## My LeetCode List 80 | 81 | [My Personal LeetCode Problem List](https://leetcode.com/list/?selectedList=pmuqba96) 82 | 83 | My personal notes: 84 | ``` 85 | If I forget . just solve 2 or 3 problem from the link 86 | ``` 87 | -------------------------------------------------------------------------------- /FLOW/Max Flow (Ford-Fulkerson) O(E * max flow).cpp: -------------------------------------------------------------------------------- 1 | // Ford-Fulkerson: 2 | // Single source, single sink 3 | // Requires integer capacities 4 | // O (E * max flow) 5 | // This is not feasible, as the value of the max flow can be very large, such as 1e18. 6 | 7 | // For understanding the complexity checkout the: Max Flow (Edmonds-Karp) O(V * E^2).cpp 8 | 9 | 10 | 11 | // Algorithm : In each iteration Find an augmenting path using DFS, then do flow augmentation through its edges. [Flow augmentation = reduce forward edges residual capacity, increase reverse edges residual capacity] 12 | 13 | const int N = 1000; 14 | 15 | struct edge 16 | { 17 | int v; // to 18 | int rev; //Reverse edge index in graph[v] 19 | int residual_capacity; // Residual capacity of the edge 20 | int edge_id; // Edge ID (optional, if needed) 21 | }; 22 | 23 | vectorgraph[N]; 24 | 25 | // This is for directed, for undirected make sure to include edges in both direction addEdge(u,v,c) and addEdge(v,u,c). 26 | void addEdge(int u, int v, int capacity, int id = -1) 27 | { 28 | graph[u].push_back({v, (int)graph[v].size(), capacity, id}); 29 | graph[v].push_back({u, (int)graph[u].size()-1, 0, -id}); 30 | } 31 | 32 | 33 | int dfs(int u, int sink, int flow, vector &visited) 34 | { 35 | if(u == sink) 36 | { 37 | return flow; 38 | } 39 | 40 | visited[u] = true; 41 | 42 | for(auto &[v, rev, residual_capacity, id] : graph[u]) 43 | { 44 | if(visited[v] || residual_capacity == 0) 45 | { 46 | continue; 47 | } 48 | 49 | int pathFlow = min(flow, residual_capacity); 50 | int pushedFlow = dfs(v, sink, pathFlow, visited); 51 | 52 | if(pushedFlow > 0) 53 | { 54 | residual_capacity -= pushedFlow; 55 | graph[v][rev].residual_capacity += pushedFlow; 56 | 57 | return pushedFlow; // we need to find only one augmenting path, so we return after any children who is giving pushFlow > 0 58 | } 59 | 60 | } 61 | 62 | return 0; // no augmenting path found 63 | } 64 | 65 | 66 | int FordFulkerson(int source ,int sink) 67 | { 68 | int maxFlow = 0; 69 | vectorvisited(N,false); 70 | 71 | while(true) 72 | { 73 | fill(visited.begin(),visited.end(),false); 74 | 75 | int flow = dfs(source, sink, INT_MAX, visited); 76 | 77 | if(flow == 0) // no augmenting path found 78 | { 79 | break; 80 | } 81 | 82 | maxFlow += flow; 83 | } 84 | 85 | return maxFlow; 86 | } 87 | 88 | 89 | int32_t main() 90 | { 91 | ios::sync_with_stdio(0); 92 | cin.tie(0); 93 | 94 | int n,m; 95 | cin>>n>>m; 96 | 97 | for(int i=0;i>u>>v>>c; 101 | addEdge(u,v,c); 102 | } 103 | 104 | cout<graph[N]; 11 | int Time[N]; 12 | bool ok; 13 | bool flag; 14 | vectorans; 15 | int parent[N]; 16 | int start,finish; 17 | 18 | void dfs(int s,int tim) 19 | { 20 | vis[s] = 1; 21 | Time[s] = tim++; 22 | for(auto child: graph[s]) 23 | { 24 | if(vis[child]==0 ) 25 | { 26 | parent[child] = s; 27 | dfs(child,tim); 28 | if(ok) 29 | { 30 | return; 31 | } 32 | } 33 | if(vis[child]==1) 34 | { 35 | 36 | start = s; 37 | finish = child; 38 | ok = true; 39 | flag = true; 40 | return; 41 | } 42 | 43 | } 44 | 45 | vis[s] = 2; 46 | 47 | 48 | } 49 | 50 | int32_t main() 51 | { 52 | ios::sync_with_stdio(0); 53 | cin.tie(0); 54 | int n,m; 55 | cin>>n>>m; 56 | 57 | for(int i=0;i>x>>y; 61 | graph[x].push_back(y); 62 | } 63 | 64 | 65 | for(int i=1;i<=n;i++) 66 | { 67 | if(vis[i]==false) 68 | { 69 | dfs(i,0); 70 | if(flag) 71 | { 72 | break; 73 | } 74 | } 75 | } 76 | 77 | 78 | if(flag) 79 | { 80 | 81 | ans.push_back(finish); 82 | 83 | while(finish!=start) 84 | { 85 | ans.push_back(start); 86 | start = parent[start]; 87 | } 88 | 89 | ans.push_back(finish); 90 | 91 | reverse(ans.begin(),ans.end()); 92 | 93 | 94 | cout<Q; 32 | 33 | 34 | //All NUMBERS are different thats why this solution works using Ordered_SET 35 | 36 | void results(vector &v , int m) 37 | { 38 | 39 | block = sqrt(v.size()+0.0); // USE block = 666; way faster 40 | 41 | sort(Q.begin() , Q.end() , cmp); 42 | 43 | int currL = 0; 44 | int currR = 0; 45 | 46 | 47 | 48 | ordered_set S; 49 | 50 | for(int i=0;iL) 58 | { 59 | S.insert(v[currL-1]); 60 | currL--; 61 | } 62 | while(currR<=R) 63 | { 64 | S.insert(v[currR]); 65 | currR++; 66 | } 67 | 68 | while(currLR+1) 76 | { 77 | int a = v[currR-1]; 78 | S.erase(a); 79 | currR--; 80 | } 81 | 82 | 83 | ans[idx] = *S.find_by_order(k-1); // 0 based bole k-1 will refer to k-th 84 | 85 | } 86 | 87 | 88 | } 89 | 90 | 91 | int32_t main() 92 | { 93 | ios::sync_with_stdio(0); 94 | cin.tie(0); 95 | 96 | int n,m; 97 | cin>>n>>m; 98 | 99 | vectorv; 100 | 101 | for(int i=0;i>a; 105 | v.push_back(a); 106 | } 107 | 108 | for(int g=0;g>i>>j>>k; 112 | Q.push_back({i-1,j-1,k,g}); 113 | } 114 | 115 | results(v,m); 116 | 117 | for(int i=0;igraph[N]; 6 | vectorRgraph[N]; 7 | bool vis1[N]; 8 | bool vis2[N]; 9 | int group_id[N]; 10 | vectorforder; 11 | 12 | void dfs1(int s) 13 | { 14 | vis1[s] = true; 15 | for(auto child : graph[s]) 16 | { 17 | if(vis1[child]) 18 | { 19 | continue; 20 | } 21 | dfs1(child); 22 | } 23 | forder.push_back(s); 24 | } 25 | void dfs2(int s , int no) 26 | { 27 | vis2[s] = true; 28 | group_id[s] = no; 29 | for(auto child : Rgraph[s]) 30 | { 31 | if(vis2[child]) 32 | { 33 | continue; 34 | } 35 | dfs2(child , no); 36 | } 37 | return; 38 | } 39 | 40 | 41 | 42 | 43 | int32_t main() 44 | { 45 | ios::sync_with_stdio(0); 46 | cin.tie(0); 47 | int n,m; 48 | cin>>n>>m; 49 | for(int i=0;i>x>>y; 53 | graph[x].push_back(y); 54 | Rgraph[y].push_back(x); 55 | } 56 | for(int i=0;iDAG[N]; 74 | //SCC to DAG convertion 75 | for(int i=0;i 12 | Strictly define what DP state means. For example: 13 | - `dp[i]` means `from 0-th to i-th element` total calculated property. Or, 14 | - `dp[i]` means `for i-th to n-th element` total calculated property. Or, 15 | - `dp[i]` means `from 0-th to i-th element` maximum/minimum calculated property. Or, 16 | - `dp[i]` means `for i-th to n-th element` maximum/minimum calculated property. Or, 17 | - Add variations based on specific problem requirements. 18 | - `dp[n+1][2]` Here `dp[i][0]` means `from 0 to i-th element` LIS with positive (current - previous) amd `dp[i][1]` means from `0 to i-th element` LIS with negetive (current-previous) 19 | 20 | ## Common Top-Down Approach 21 | ```cpp 22 | int f(int n) { 23 | if (n <= 1) { 24 | return n; 25 | } 26 | 27 | if (dp[n] != -1) { 28 | return dp[n]; 29 | } 30 | 31 | // Define transitions or loops if necessary. 32 | 33 | dp[n] = f(n - 1) + f(n - 2); 34 | 35 | return dp[n]; 36 | } 37 | ``` 38 | ## Common Bottom-Up Approach 39 | Most of linear DP is solved using the bottom-up approach because there is only one state, and the transition relation is not that hard to find from the bottom or start state to the final state. 40 | 41 | ```cpp 42 | dp[1] = 1; 43 | 44 | for (int i = 2; i <= n; ++i) { 45 | // Define the transition relation based on the problem. 46 | dp[i] = dp[i - 1] + dp[i - 2]; 47 | } 48 | 49 | return dp[n]; 50 | ``` 51 | --- 52 | 53 | # Linear DP Common Problems: 54 | - Coin change all variant 55 | - LIS 56 | - Fibonacci 57 | 58 | **To solve most of the linear dp problems we have to think like coin change dp variants.**
59 | Cause they are the best representative on how to get ans from already linearly calculated previous states. Also LIS is an amazing example for getting the ans like this 60 | ```cpp 61 | for(int i=0;i 10 | #include 11 | #include 12 | using namespace std; 13 | #define endl "\n" 14 | #define inf 1000000000000000000 15 | #define int long long int 16 | 17 | namespace __gnu_pbds{ 18 | typedef tree, // in the previous template, just using less_equal in place of less , will do the trick. 21 | rb_tree_tag, 22 | tree_order_statistics_node_update> ordered_set; 23 | } 24 | using namespace __gnu_pbds; 25 | 26 | 27 | void Insert(ordered_set &s,int x){ //this function inserts one more occurrence of (x) into the set. 28 | 29 | s.insert(x); 30 | 31 | } 32 | 33 | 34 | bool Exist(ordered_set &s,int x){ //this function checks weather the value (x) exists in the set or not. 35 | 36 | if((s.upper_bound(x))==s.end()){ 37 | return 0; 38 | } 39 | return ((*s.upper_bound(x))==x); 40 | 41 | } 42 | 43 | 44 | void Erase(ordered_set &s,int x){ //this function erases one occurrence of the value (x). 45 | 46 | if(Exist(s,x)){ 47 | s.erase(s.upper_bound(x)); 48 | } 49 | 50 | } 51 | 52 | 53 | int FirstIdx(ordered_set &s,int x){ //this function returns the first index of the value (x)..(0 indexing). 54 | 55 | if(!Exist(s,x)){ 56 | return -1; 57 | } 58 | return (s.order_of_key(x)); 59 | 60 | } 61 | 62 | 63 | int Value(ordered_set &s,int idx){ //this function returns the value at the index (idx)..(0 indexing). 64 | 65 | return (*s.find_by_order(idx)); 66 | 67 | } 68 | 69 | 70 | int LastIdx(ordered_set &s,int x){ //this function returns the last index of the value (x)..(0 indexing). 71 | 72 | if(!Exist(s,x)){ 73 | return -1; 74 | } 75 | if(Value(s,(int)s.size()-1)==x){ 76 | return (int)(s.size())-1; 77 | } 78 | return FirstIdx(s,*s.lower_bound(x))-1; 79 | 80 | } 81 | 82 | 83 | int Count(ordered_set &s,int x){ //this function returns the number of occurrences of the value (x). 84 | 85 | if(!Exist(s,x)){ 86 | return 0; 87 | } 88 | return LastIdx(s,x)-FirstIdx(s,x)+1; 89 | 90 | } 91 | 92 | 93 | void Clear(ordered_set &s){ //this function clears all the elements from the set. 94 | 95 | s.clear(); 96 | 97 | } 98 | 99 | 100 | int Size(ordered_set &s){ //this function returns the size of the set. 101 | 102 | return (int)(s.size()); 103 | 104 | } 105 | 106 | 107 | 108 | 109 | int32_t main() 110 | { 111 | ios::sync_with_stdio(0); 112 | cin.tie(0); 113 | 114 | // 115 | 116 | 117 | } 118 | -------------------------------------------------------------------------------- /STRINGS/KMP.cpp: -------------------------------------------------------------------------------- 1 | 2 | // KMP Algorithm : the motto is, 3 | // Longest suffix that ends at i, which is also a prefix 4 | 5 | vectorprefix_function(string &s) 6 | { 7 | int n = s.size(); 8 | vectorphi(n); 9 | 10 | for(int i=1;i 0 && s[j] != s[i]) 15 | { 16 | j = phi[j-1]; 17 | } 18 | 19 | if(s[i] == s[j]) 20 | { 21 | j++; 22 | } 23 | 24 | phi[i] = j; 25 | } 26 | return phi; 27 | } 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | // UVA 455 - Periodic Strings 40 | // https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=396 41 | 42 | ============ Solve with KMP ======== 43 | 44 | 45 | //Intermediary 46 | //Young kid on the block 47 | //AIAsif try's Continuing the journey 48 | #include 49 | #include 50 | #include 51 | using namespace std; 52 | using namespace __gnu_pbds; 53 | #define endl "\n" 54 | #define inf 1000000000000000000 55 | #define int long long int 56 | #define ordered_set tree< int, null_type, less, rb_tree_tag,tree_order_statistics_node_update> 57 | 58 | 59 | 60 | 61 | // KMP Algorithm : the motto is, 62 | // Longest suffix that ends at i, which is also a prefix 63 | 64 | vectorprefix_function(string &s) 65 | { 66 | int n = s.size(); 67 | vectorphi(n); 68 | 69 | for(int i=1;i 0 && s[j] != s[i]) 74 | { 75 | j = phi[j-1]; 76 | } 77 | 78 | if(s[i] == s[j]) 79 | { 80 | j++; 81 | } 82 | 83 | phi[i] = j; 84 | } 85 | return phi; 86 | } 87 | 88 | 89 | 90 | int32_t main() 91 | { 92 | ios::sync_with_stdio(0); 93 | cin.tie(0); 94 | 95 | 96 | 97 | int t; 98 | cin>>t; 99 | 100 | for(int tt=1;tt<=t;tt++) 101 | { 102 | string s; 103 | cin>>s; 104 | 105 | vectorphi = prefix_function(s); 106 | 107 | int n = s.size(); 108 | 109 | int repeat_start = n - phi[n-1]; 110 | 111 | 112 | if(n%repeat_start == 0) 113 | { 114 | cout<>graph[N]; 11 | bool vis[N]; 12 | const int L = log2(N); 13 | int up[N][L+1]; 14 | int sum[N]; 15 | int din[N]; 16 | int dout[N]; 17 | int tin; 18 | int tout; 19 | 20 | void dfs(int s,int par) 21 | { 22 | vis[s] = true; 23 | up[s][0] = par; 24 | 25 | din[s] = tin++; 26 | for(int i=1;i<=L;i++) 27 | { 28 | up[s][i] = up[ up[s][i-1] ][i-1]; 29 | } 30 | 31 | for(auto child : graph[s]) 32 | { 33 | if(vis[child.first]) 34 | { 35 | continue; 36 | } 37 | 38 | sum[child.first] = sum[s] + child.second; // here storing prefix sum 39 | 40 | dfs(child.first,s); 41 | } 42 | dout[s] = tout++; 43 | } 44 | 45 | bool is_ancestor(int u,int v) 46 | { 47 | if(din[u]<=din[v] && dout[u]>=dout[v]) 48 | { 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | int lca(int u,int v) 55 | { 56 | if(is_ancestor(u,v)) 57 | { 58 | return u; 59 | } 60 | if(is_ancestor(v,u)) 61 | { 62 | return v; 63 | } 64 | for(int i=L;i>=0;i--) 65 | { 66 | if(!is_ancestor(up[u][i] , v)) 67 | { 68 | u = up[u][i]; 69 | } 70 | } 71 | return up[u][0]; 72 | } 73 | 74 | 75 | int32_t main() 76 | { 77 | ios::sync_with_stdio(0); 78 | cin.tie(0); 79 | int n; 80 | cin>>n; 81 | for(int i=0;i>x>>y>>w; 85 | graph[x].push_back({y,w}); 86 | graph[y].push_back({x,w}); 87 | } 88 | 89 | dfs(1,1); 90 | 91 | int q; 92 | cin>>q; 93 | while(q--) 94 | { 95 | int u,v; 96 | cin>>u>>v; 97 | 98 | int l = lca(u,v); 99 | 100 | if(l==u || l==v) 101 | { 102 | cout< 0) 72 | { 73 | cur = node[cur][s[i]-'a']; 74 | } 75 | else 76 | { 77 | return false; 78 | } 79 | } 80 | 81 | return true; 82 | } 83 | 84 | 85 | bool Search(string s) 86 | { 87 | int cur = root; 88 | for(int i=0;i 0) 91 | { 92 | cur = node[cur][s[i]-'a']; 93 | } 94 | else 95 | { 96 | return false; 97 | } 98 | } 99 | 100 | return (is_end[cur]>0); 101 | } 102 | 103 | 104 | 105 | int32_t main() 106 | { 107 | ios::sync_with_stdio(0); 108 | cin.tie(0); 109 | 110 | 111 | ini(); 112 | 113 | int n; 114 | cin>>n; 115 | 116 | while(n--) 117 | { 118 | string s; 119 | cin>>s; 120 | Insert(s); 121 | } 122 | 123 | string a; 124 | cin>>a; 125 | 126 | cout<>b; 132 | 133 | Remove(b); // asuming b is present in trie 134 | 135 | cout< 0) 72 | { 73 | cur = node[cur][s[i]-'a']; 74 | } 75 | else 76 | { 77 | return false; 78 | } 79 | } 80 | 81 | return true; 82 | } 83 | 84 | 85 | bool Search(string s) 86 | { 87 | int cur = root; 88 | for(int i=0;i 0) 91 | { 92 | cur = node[cur][s[i]-'a']; 93 | } 94 | else 95 | { 96 | return false; 97 | } 98 | } 99 | 100 | return (is_end[cur]>0); 101 | } 102 | 103 | 104 | 105 | int32_t main() 106 | { 107 | ios::sync_with_stdio(0); 108 | cin.tie(0); 109 | 110 | 111 | ini(); 112 | 113 | int n; 114 | cin>>n; 115 | 116 | while(n--) 117 | { 118 | string s; 119 | cin>>s; 120 | Insert(s); 121 | } 122 | 123 | string a; 124 | cin>>a; 125 | 126 | cout<>b; 132 | 133 | Remove(b); // asuming b is present in trie 134 | 135 | cout<graph[N]; 22 | int in[N]; 23 | vectordis(N,-inf); 24 | int parent[N]; 25 | 26 | int32_t main() 27 | { 28 | ios::sync_with_stdio(0); 29 | cin.tie(0); 30 | int n,m; 31 | cin>>n>>m; 32 | for(int i=0;i>x>>y; 36 | graph[x].push_back(y); 37 | in[y]++; 38 | } 39 | queueq; 40 | 41 | for(int i=1;i<=n;i++) 42 | { 43 | if(in[i]==0) 44 | { 45 | q.push(i); 46 | } 47 | } 48 | vectortopo; 49 | while(!q.empty()) 50 | { 51 | int father = q.front(); 52 | topo.push_back(father); 53 | q.pop(); 54 | 55 | 56 | for(auto child: graph[father]) 57 | { 58 | in[child]--; 59 | if(in[child]==0) 60 | { 61 | q.push(child); 62 | } 63 | } 64 | } 65 | 66 | dis[1] = 0; 67 | 68 | for(auto s : topo) 69 | { 70 | if(dis[s]!=-inf) 71 | { 72 | for(auto child: graph[s]) 73 | { 74 | if(dis[child]ans; 96 | 97 | while(v!=0) 98 | { 99 | ans.push_back(v); 100 | v = parent[v]; 101 | } 102 | reverse(ans.begin(),ans.end()); 103 | 104 | cout<Tree[4*N]; // each node will store (indexes) in sorted order 12 | vector>A; 13 | 14 | 15 | void build(int node,int lo,int hi) 16 | { 17 | if(lo==hi) 18 | { 19 | Tree[node].push_back(A[lo].second); // indexex will be stored at every node in sorted order 20 | return; 21 | } 22 | 23 | int mid = (lo+hi)>>1; 24 | 25 | build(node*2,lo,mid); 26 | build(node*2+1 , mid+1,hi); 27 | 28 | merge(Tree[node*2].begin() , Tree[node*2].end() , Tree[node*2+1].begin() , Tree[node*2+1].end() , back_inserter(Tree[node])); // this merge fuction works excatly like merge in mergeSort [watch gfg] 29 | 30 | 31 | } 32 | 33 | int query(int node ,int lo,int hi,int i,int j,int k) 34 | { 35 | if(lo==hi) 36 | { 37 | return Tree[node][0]; 38 | } 39 | int mid = (lo+hi)>>1; 40 | 41 | int a = lower_bound(Tree[node*2].begin() , Tree[node*2].end() , i)-Tree[node*2].begin(); 42 | int b = upper_bound(Tree[node*2].begin() , Tree[node*2].end() , j)-Tree[node*2].begin(); 43 | 44 | int M = b-a; // [i:j] range er moddhe koyta indexes ase in Tree[node*2] Tee 45 | 46 | if(M>=k) 47 | { 48 | //Tree[node*2] tee thaka indexes er songkha greater than K hoy taile k-th minimum er index will exits here 49 | return query(node*2 , lo , mid , i , j , k); 50 | } 51 | else 52 | { 53 | //let say k = 6 and M = 4 : 54 | //er ortho hocce [i:j] range er 4 ta indexes exists kore Tree[node*2] te 55 | 56 | // baki 2 ta indexes exits here : k-M 57 | 58 | //Keep in mind that elements at the right childs > elements at the left childs . thats why we have to pass k-M here to get k-th minimum number er index 59 | 60 | return query(node*2+1 , mid+1 , hi , i , j , k-M); 61 | } 62 | 63 | 64 | } 65 | 66 | 67 | int32_t main() 68 | { 69 | ios::sync_with_stdio(0); 70 | cin.tie(0); 71 | 72 | int n , q; 73 | cin>>n>>q; 74 | 75 | vectorv; 76 | for(int i=0;i>a; 80 | v.push_back(a); 81 | } 82 | 83 | for(int i=0;i>i>>j>>k; //i,j 1-based 96 | 97 | int kthminimumdx = query(1,0,n-1,i-1,j-1,k); // pass 0-based 98 | 99 | cout< 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace __gnu_pbds; 9 | #define endl "\n" 10 | #define inf 1000000000000000000 11 | #define int long long int 12 | #define ordered_set tree, rb_tree_tag, tree_order_statistics_node_update> 13 | 14 | const int N = 1e6; 15 | vectorcoins; 16 | int dp[N]; 17 | 18 | int32_t main() 19 | { 20 | ios::sync_with_stdio(0); 21 | cin.tie(0); 22 | 23 | 24 | ### 1.Using given coins any number of times how many ways I can make `n`. where order matters. (3+1=4 , 1+3=4 counted different) 25 | 26 | dp[0] = 1; 27 | 28 | for (int i = 1; i <= n; ++i) 29 | { 30 | for(int j=0;j= 0) 33 | { 34 | dp[i] += dp[i - coins[j]]; 35 | } 36 | } 37 | } 38 | 39 | 40 | 41 | ### 2.Using given coins any number of times how many ways I can make `n`. where order does not matters. (3+1=4 , 1+3=4 counted once) 42 | 43 | dp[0] = 1; 44 | for(int i=0;i=0) 49 | { 50 | dp[j] += dp[j-coins[i]]; 51 | } 52 | 53 | } 54 | } 55 | 56 | 57 | 58 | ### 3.Using given coins atmost once how many ways I can make `n`. where order does not matters. (3+1=4 , 1+3=4 counted once) 59 | 60 | dp[0] = 1; 61 | 62 | for (int i = 0; i < coins.size(); ++i) 63 | { 64 | for (int j = n; j >= 0 ;j--) // Since I cant use any coin more than onces that's why we starts from j=n . To stop over counting 65 | { 66 | if(j-coins[i]>=0) 67 | { 68 | dp[j] += dp[j - coins[i]]; 69 | } 70 | 71 | } 72 | } 73 | 74 | 75 | ### 4.Using minimum number of coins make 'n' . you can use one coin more than once 76 | 77 | vector dp(n + 1, INT_MAX); 78 | 79 | dp[0] = 0; 80 | 81 | for (int i = 1; i <= n; ++i) 82 | { 83 | for(int j=0;j= 0) 86 | { 87 | dp[i] = min(dp[i], dp[i - coins[j]] + 1); 88 | } 89 | } 90 | } 91 | 92 | 93 | ### 5.Using minimum number of coins make 'n' . you can use one coin atmost once 94 | 95 | dp[0] = 0; 96 | 97 | for(int i=0;i= 0; --j) // Since I cant use any coin more than onces that's why we starts from j=n . To stop over counting 100 | { 101 | if(j-coins[i]>=0) 102 | { 103 | dp[j] = min(dp[j], dp[j - coins[i]] + 1); 104 | } 105 | 106 | } 107 | } 108 | 109 | 110 | 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /TECHNIQUES/Inclusion Exclusion .cpp: -------------------------------------------------------------------------------- 1 | // excellent problem on inclusion exclusion 2 | // Nailed By me ,,, only only meee 3 | 4 | Solution of the Problem is given below 5 | https://codeforces.com/contest/1295/problem/D 6 | 7 | 8 | const int N = 1e6; 9 | bool sieve[N]; 10 | vectorprime; 11 | 12 | void pre() 13 | { 14 | memset(sieve , true, sizeof(sieve)); 15 | 16 | for(int i=2;i fact(int n) 36 | { 37 | mapm; 38 | 39 | for(int i=0;i1) 48 | { 49 | m[n]++; 50 | } 51 | 52 | return m; 53 | } 54 | 55 | int32_t main() 56 | { 57 | ios::sync_with_stdio(0); 58 | cin.tie(0); 59 | 60 | pre(); 61 | 62 | int t; 63 | cin>>t; 64 | 65 | while(t--) 66 | { 67 | int a,m; 68 | cin>>a>>m; 69 | 70 | int test = __gcd(a,m); 71 | 72 | mapfact1; 73 | mapfact2; 74 | 75 | fact1 = fact(m); 76 | 77 | fact2 = fact(test); 78 | 79 | if(test!=1) 80 | { 81 | for(auto x : fact2) 82 | { 83 | fact1[x.first]-=x.second; 84 | } 85 | } 86 | 87 | 88 | vectorv; 89 | 90 | for(auto x : fact1) 91 | { 92 | if(x.second!=0) 93 | { 94 | v.push_back(x.first); 95 | } 96 | } 97 | 98 | int ans = (a+m-1)/test - (a-1)/test ; 99 | 100 | for(int i=1;i<(1< man; 6 | int n; 7 | 8 | Manacher(const string& s) 9 | { 10 | n = s.size(); 11 | if (n == 0) return; 12 | 13 | int l = 0, r = -1; 14 | vector d1(n); 15 | 16 | for (int i = 0; i < n; i++) 17 | { 18 | int k = i > r ? 1 : min(d1[l + r - i], r - i); 19 | while (i + k < n && i - k >= 0 && s[i + k] == s[i - k]) 20 | { 21 | 22 | k++; 23 | } 24 | 25 | d1[i] = k--; 26 | 27 | if (i + k > r) 28 | { 29 | l = i - k, r = i + k; 30 | } 31 | } 32 | 33 | 34 | l = 0, r = -1; 35 | vector d2(n); 36 | for (int i = 0; i < n; i++) 37 | { 38 | int k = i > r ? 0 : min(d2[l + r - i + 1], r - i + 1); 39 | 40 | k++; 41 | 42 | 43 | while (i + k <= n && i - k >= 0 && s[i + k - 1] == s[i - k]) 44 | { 45 | k++; 46 | } 47 | 48 | d2[i] = --k; 49 | 50 | 51 | if (i + k - 1 > r) 52 | { 53 | l = i - k; 54 | r = i + k - 1; 55 | } 56 | } 57 | 58 | 59 | man.resize(2 * n - 1); 60 | 61 | for (int i = 0; i < n; i++) 62 | { 63 | man[2 * i] = 2 * d1[i] - 1; 64 | } 65 | for (int i = 0; i < n - 1; i++) 66 | { 67 | man[2 * i + 1] = 2 * d2[i + 1]; 68 | } 69 | 70 | } 71 | 72 | // Check if substring s[i..j] is a palindrome 73 | bool isPalindrome(int i, int j) 74 | { 75 | if (i > j) 76 | { 77 | return true; 78 | } 79 | return man[i + j] >= j - i + 1; 80 | } 81 | 82 | // Returns vector where ret[i] is the length of the longest palindrome 83 | // ending at index i. 84 | vector getEndingLengths() 85 | { 86 | if (n == 0) return {}; 87 | 88 | vector ret(n); 89 | 90 | ret[0] = 1; 91 | for (int i = 1; i < n; i++) 92 | { 93 | ret[i] = min(ret[i - 1] + 2, i + 1); 94 | 95 | while (!isPalindrome(i - ret[i] + 1, i)) 96 | { 97 | ret[i]--; 98 | } 99 | } 100 | return ret; 101 | } 102 | }; 103 | 104 | 105 | 106 | int32_t main() 107 | { 108 | string s; 109 | cin>>s; 110 | 111 | Manacher m(s); 112 | 113 | vector lengths = m.getEndingLengths(); 114 | 115 | for(int i=0;i>1; 26 | 27 | Tree[node*2].val += (mid-lo+1)*temp; // lazy pawar sathe sathei sob node e add kore disi , tai query korar somoy node er Lazy add korte hobe na 28 | Tree[node*2+1].val +=(hi-(mid+1)+1)*temp; // // lazy pawar sathe sathei sob node e add kore disi , tai query korar somoy node er Lazy add korte hobe na 29 | } 30 | 31 | 32 | void build(int node,int lo,int hi) 33 | { 34 | if(lo==hi) 35 | { 36 | Tree[node].val = ara[lo]; 37 | return; 38 | } 39 | 40 | int mid = (lo+hi)>>1; 41 | 42 | build(node*2,lo,mid); 43 | build(node*2+1 , mid+1,hi); 44 | 45 | Tree[node].val = Tree[node*2].val + Tree[node*2+1].val; 46 | } 47 | 48 | void update(int node,int lo,int hi,int i,int j , int val) 49 | { 50 | if(Tree[node].lazy>0) 51 | { 52 | propagate(node,lo,hi); 53 | } 54 | if(hij) 55 | { 56 | return; 57 | } 58 | if(lo>=i && hi<=j) 59 | { 60 | Tree[node].lazy += val; 61 | Tree[node].val += (hi-lo+1)*val; // ekhanei sob node e add kore disi , tai query korar somoy node er Lazy add korte hobe na 62 | 63 | return; 64 | } 65 | 66 | int mid = (lo+hi)>>1; 67 | update(node*2,lo,mid,i,j,val); 68 | update(node*2+1,mid+1,hi,i,j,val); 69 | 70 | Tree[node].val = Tree[node*2].val + Tree[node*2+1].val; 71 | } 72 | 73 | int query(int node,int lo,int hi,int i,int j) 74 | { 75 | if(Tree[node].lazy>0) 76 | { 77 | propagate(node,lo,hi); 78 | } 79 | if(hij) 80 | { 81 | return 0; 82 | } 83 | if(lo>=i && hi<=j) 84 | { 85 | return Tree[node].val; 86 | } 87 | int mid = (lo+hi)>>1; 88 | 89 | int x = query(node*2,lo,mid,i,j); 90 | int y = query(node*2+1,mid+1,hi,i,j); 91 | 92 | return x+y; 93 | 94 | } 95 | 96 | 97 | int32_t main() 98 | { 99 | ios::sync_with_stdio(0); 100 | cin.tie(0); 101 | 102 | int n; 103 | cin>>n; 104 | for(int i=1;i<=n;i++) 105 | { 106 | cin>>ara[i]; 107 | } 108 | 109 | build(1,1,n); 110 | 111 | int q; 112 | cin>>q; 113 | while(q--) 114 | { 115 | int a; 116 | cin>>a; 117 | if(a==1) 118 | { 119 | int i,j,x; 120 | cin>>i>>j>>x; 121 | update(1,1,n,i,j,x); 122 | } 123 | else 124 | { 125 | int i,j; 126 | cin>>i>>j; 127 | cout<graph[N]; 4 | int low[N]; 5 | int dis[N]; 6 | vectorpar(N,-1); 7 | bool vis[N]; 8 | vector>p[N]; 9 | int no = 1; 10 | 11 | void dfs(int s, stack> &st , int time) 12 | { 13 | time++; 14 | vis[s] = true; 15 | low[s] = dis[s] = time; 16 | int childno = 0; 17 | for(auto child : graph[s]) 18 | { 19 | if(par[s]==child) 20 | { 21 | continue; 22 | } 23 | if(vis[child]) 24 | { 25 | low[s] = min(low[s] , dis[child]); 26 | if(dis[child]1) || (par[s]!=-1 && dis[s]<=low[child]) ) 42 | { 43 | while(st.top().first!=s || st.top().second!= child) 44 | { 45 | p[no].push_back({st.top().first ,st.top().second }); 46 | st.pop(); 47 | } 48 | p[no].push_back({st.top().first ,st.top().second }); 49 | st.pop(); 50 | no++; 51 | } 52 | } 53 | } 54 | 55 | 56 | int32_t main() 57 | { 58 | ios::sync_with_stdio(0); 59 | cin.tie(0); 60 | int n,m; 61 | cin>>n>>m; 62 | for(int i=0;i>x>>y; 66 | graph[x].push_back(y); 67 | graph[y].push_back(x); 68 | } 69 | stack>st; 70 | for(int i=0;i graph[N]; 21 | int level[N]; 22 | int done[N]; // done[u] array is to keep track of which edges have already been tried for a given node during a DFS call. This ensures that we don't revisit the same edges unnecessarily and speeds up the process. 23 | 24 | 25 | // This is for directed, for undirected make sure to include edges in both direction addEdge(u,v,c) and addEdge(v,u,c). 26 | void addEdge(int u, int v, int capacity, int id = -1) 27 | { 28 | graph[u].push_back({v, (int)graph[v].size(), capacity, id}); 29 | graph[v].push_back({u, (int)graph[u].size()-1, 0, -id}); 30 | } 31 | 32 | 33 | // BFS to build Level Graph 34 | bool bfs(int source, int sink) 35 | { 36 | fill(level, level+N, -1); 37 | level[source] = 0; 38 | queueq; 39 | q.push(source); 40 | 41 | while(!q.empty()) 42 | { 43 | int u = q.front(); 44 | q.pop(); 45 | 46 | for(auto &[v, rev, residual_capacity, id]: graph[u]) 47 | { 48 | if(level[v] != -1 || residual_capacity == 0) 49 | { 50 | continue; 51 | } 52 | 53 | level[v] = level[u] + 1; 54 | q.push(v); 55 | } 56 | } 57 | 58 | return level[sink] != -1; // sink is reachable = true 59 | } 60 | 61 | 62 | 63 | // DFS to send flow along augmenting paths 64 | int dfs(int u, int sink, int flow) 65 | { 66 | if(u == sink) 67 | { 68 | return flow; 69 | } 70 | 71 | for(; done[u] < graph[u].size(); done[u]++) 72 | { 73 | auto &[v, rev, residual_capacity, id] = graph[u][done[u]]; 74 | 75 | if(level[v] == level[u]+1 && residual_capacity > 0) // only traversing trough level graph 76 | { 77 | int pathFlow = min(flow, residual_capacity); 78 | int pushedFlow = dfs(v, sink, pathFlow); 79 | 80 | if(pushedFlow > 0) 81 | { 82 | residual_capacity -= pushedFlow; 83 | graph[v][rev].residual_capacity += pushedFlow; 84 | 85 | return pushedFlow; 86 | } 87 | } 88 | } 89 | 90 | return 0; 91 | } 92 | 93 | 94 | int Dinic(int source, int sink) 95 | { 96 | int max_flow = 0; 97 | 98 | while(bfs(source, sink)) // build the level graph 99 | { 100 | fill(done, done+N, 0); 101 | 102 | while(true) // traverse on the same level graph multiple time, which is efficiant than Edmonds-Karp. As we are blocking multiple edges(residual_capacity = 0) using the same level graph. 103 | { 104 | int flow = dfs(source, sink, inf); 105 | 106 | if(flow == 0) 107 | { 108 | break; 109 | } 110 | 111 | max_flow += flow; 112 | } 113 | 114 | } 115 | 116 | return max_flow; 117 | } 118 | 119 | 120 | int32_t main() 121 | { 122 | ios::sync_with_stdio(0); 123 | cin.tie(0); 124 | 125 | int n,m; 126 | cin>>n>>m; 127 | for(int i=0;i>u>>v>>c; 131 | addEdge(u,v,c); 132 | } 133 | 134 | cout<graph[N]; 27 | 28 | 29 | // This is for directed, for undirected make sure to include edges in both direction addEdge(u,v,c) and addEdge(v,u,c). 30 | void addEdge(int u, int v, int capacity, int id = -1) 31 | { 32 | graph[u].push_back({v, (int)graph[v].size(), capacity, id}); 33 | graph[v].push_back({u, (int)graph[u].size()-1, 0, -id}); 34 | } 35 | 36 | int bfs(int source, int sink, vector> &parent) 37 | { 38 | for(int i=0;ivisited(N, false); 44 | 45 | visited[source] = true; 46 | queueq; 47 | q.push(source); 48 | 49 | int flow = INT_MAX; 50 | 51 | while(!q.empty()) 52 | { 53 | int u = q.front(); 54 | q.pop(); 55 | 56 | for(auto &[v, rev, residual_capacity, id] : graph[u]) 57 | { 58 | if(visited[v] || residual_capacity == 0) 59 | { 60 | continue; 61 | } 62 | 63 | flow = min(flow, residual_capacity); 64 | 65 | parent[v] = {u,rev}; // rev contains index of u in graph[v] 66 | 67 | visited[v] = true; 68 | 69 | if(v == sink) 70 | { 71 | return flow; 72 | } 73 | 74 | q.push(v); 75 | 76 | 77 | 78 | } 79 | } 80 | 81 | return 0; // no augmenting path 82 | } 83 | 84 | 85 | int Edmonds_Karp(int source, int sink) 86 | { 87 | int max_flow = 0; 88 | 89 | vector>parent(N, {-1,-1}); // parent[v] = {u, rev}, where rev contains index of u in graph[v] 90 | 91 | while(true) 92 | { 93 | int flow = bfs(source, sink, parent); 94 | 95 | if(flow == 0) 96 | { 97 | break; 98 | } 99 | 100 | max_flow += flow; 101 | 102 | int v = sink; 103 | 104 | while(v != source) 105 | { 106 | int u = parent[v].first; 107 | int rev = parent[v].second; 108 | 109 | graph[v][rev].residual_capacity += flow; 110 | graph[u][graph[v][rev].rev].residual_capacity -= flow; 111 | 112 | v = parent[v].first; 113 | } 114 | } 115 | 116 | return max_flow; 117 | } 118 | 119 | 120 | 121 | int32_t main() 122 | { 123 | ios::sync_with_stdio(0); 124 | cin.tie(0); 125 | 126 | int n,m; 127 | cin>>n>>m; 128 | 129 | for(int i=0;i>u>>v>>w; 133 | 134 | addEdge(u,v,w); 135 | } 136 | 137 | cout<val = 0; 31 | return; 32 | } 33 | n->left = new node(NULL,NULL,0); 34 | n->right = new node(NULL,NULL,0); 35 | 36 | int mid = (lo+hi)>>1; 37 | 38 | build(n->left,lo,mid); 39 | build(n->right,mid+1,hi); 40 | 41 | n->val = 0; 42 | 43 | } 44 | 45 | void update(node *prev, node *cur ,int lo,int hi,int pos,int val) 46 | { 47 | if(pos>hi || poshi) 48 | { 49 | return; 50 | } 51 | if(lo==hi) 52 | { 53 | cur->val = prev->val; //If elements are not distinct , we need to add previous values too : else just cur->val = 1 would works 54 | cur->val += val; 55 | 56 | return; 57 | } 58 | int mid = (lo+hi)>>1; 59 | 60 | if(pos<=mid) 61 | { 62 | cur->right = prev->right; 63 | cur->left = new node(NULL , NULL,0); 64 | update(prev->left , cur->left , lo,mid,pos,val); 65 | } 66 | else 67 | { 68 | cur->left = prev->left; 69 | cur->right = new node(NULL , NULL,0); 70 | update(prev->right , cur->right , mid+1,hi,pos,val); 71 | } 72 | 73 | cur->val = cur->left->val + cur->right->val; 74 | 75 | 76 | } 77 | 78 | int query(node *j , node *i ,int lo,int hi,int k) 79 | { 80 | if(lo==hi) 81 | { 82 | return lo; 83 | } 84 | int M = (j->left->val) - (i->left->val); 85 | 86 | 87 | int mid = (lo+hi)>>1; 88 | 89 | 90 | if(M>=k) 91 | { 92 | return query(j->left,i->left,lo,mid,k); 93 | } 94 | else 95 | { 96 | return query(j->right,i->right,mid+1,hi,k-M); 97 | } 98 | } 99 | 100 | int32_t main() 101 | { 102 | ios::sync_with_stdio(0); 103 | cin.tie(0); 104 | int n,m; 105 | cin>>n>>m; 106 | 107 | version[0] = new node(NULL,NULL,0); 108 | 109 | 110 | build(version[0],1,n); // empty segment tree 111 | 112 | vectorv; 113 | 114 | for(int i=1;i<=n;i++) 115 | { 116 | int a; 117 | cin>>a; 118 | arr[i] = a; 119 | v.push_back(a); 120 | } 121 | sort(v.begin(),v.end()); 122 | 123 | for(int i=1;i<=n;i++) 124 | { 125 | arr[i] = lower_bound(v.begin(),v.end(),arr[i])-v.begin() + 1; // converting all the elements to (0 < arr[i] <= n) 126 | //Here arr[i] = arr[i]-th element in vector v; //THis makes sure we getting the position rather than the number . This will make sure Histogram fenwick tree < N size 127 | } 128 | 129 | for(int i=1;i<=n;i++) 130 | { 131 | version[i] = new node(NULL,NULL,0); // this line must be here : if we allocate space for versions before here we shall get RUN TIME ERROR due to unused allocations 132 | update(version[i-1],version[i],1,n,arr[i],1); 133 | } 134 | 135 | while(m--) 136 | { 137 | int l,r,k; 138 | cin>>l>>r>>k; 139 | 140 | int idx = query(version[r],version[l-1],1,n,k); 141 | 142 | 143 | //(idx - 1)-th element in vector V is the ans : [think the Fenwick tree implementation of Order statistices tree 144 | 145 | cout< Moves[j]) 68 | { 69 | // Accumulate values to calculate dp[i] 70 | dp[i] += dp[i - Moves[j]]; 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | Before calculating `dp[i]`, we already have `dp[i - Moves[j]]` calculated, which optimizes the computation. 77 | 78 | **Execution Flow: Initial State ⟶⟶⟶⟶ Target State** 79 | 80 | --- 81 | 82 | # *Solving DP problems Step - 01* : 83 | [![One and Only Step](https://img.shields.io/badge/One_and_Only_Step-blue.svg?style=for-the-badge)](https://your-link-here.com) 84 | 85 | Read the problem carefully and declare the DP states . *For a very good habit , declare the dp states by commenting at the right of `dp[n]` array* . 86 | 87 | *For examples*: 88 | ```cpp 89 | //coin dp 90 | int dp[n+1]; // dp[i] means total number way to make i money 91 | ``` 92 | 93 | ```cpp 94 | //digit dp 95 | int dp[22][4][2]; //dp[next N digits][non_zero_left][tight] 96 | ``` 97 | 98 | ```cpp 99 | //lis dp 100 | int dp[n+1][2]; // dp[i][0] means from 0 to i LIS with positive (current - previous) ; dp[i][1] means from 0 to i LIS with negetive (current-previous) 101 | ``` 102 | *So on....* 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /TREE ALGOs/LCA in O(1).cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | // ============= Euler Tour type - 03 ========== LCA in O(1) ============ 4 | 5 | // ET3 = 1 2 3 2 4 6 4 7 4 2 5 2 1 8 9 8 10 8 1 6 | 7 | // in this tour technique (child - father - child) is always maintained , so between 2 child , their father shall be present (not grand father though) 8 | // So query(u,v) means : 9 | // u first appear in ET3 and v first appear in ET3 er moddhe jetar depth lowest setai LCA ; 10 | // we find this using sparse table O(1) , segment tree O(logn) 11 | 12 | 13 | const int N = 1e5; 14 | vectorgraph[N]; 15 | vectorET3; 16 | vectorp(N,-1); //p[v] = v first appear in ET3; 17 | bool vis[N]; 18 | int dept[N]; 19 | const int L = log2(N); 20 | int st[N][L+1]; 21 | int Log2[N]; 22 | 23 | void dfs(int s) 24 | { 25 | vis[s] = true; 26 | ET3.push_back(s); 27 | for(auto child: graph[s]) 28 | { 29 | if(vis[child]) 30 | { 31 | continue; 32 | } 33 | dept[child] = dept[s]+1; 34 | 35 | dfs(child); 36 | 37 | ET3.push_back(s); 38 | } 39 | } 40 | 41 | void pre() 42 | { 43 | Log2[0] = 0; 44 | Log2[1] = 0; 45 | Log2[2] = 1; 46 | for(int i=3;i>n; 94 | for(int i=0;i>x>>y; 98 | graph[x].push_back(y); 99 | graph[y].push_back(x); 100 | } 101 | 102 | dfs(1); 103 | 104 | for(int i=0;i>q; 117 | 118 | 119 | cout<<"LCAs : "<>u>>v; 124 | 125 | 126 | int a = min(p[v],p[u]); // p[u] first pos of u , p[v] first pos of v in ET3; 127 | int b = max(p[v],p[u]); 128 | 129 | int i = Log2[b-a+1]; 130 | 131 | int vertex1 = st[a][i]; 132 | int vertex2 = st[b-(1< 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace __gnu_pbds; 11 | #define endl "\n" 12 | #define int long long int 13 | #define ordered_set tree< int, null_type, less, rb_tree_tag,tree_order_statistics_node_update> 14 | 15 | const int N = 1e5+100; 16 | vectorgraph[N]; 17 | bool vis[N]; 18 | int vis_time_vertex[N]; 19 | int in[N]; 20 | int out[N]; 21 | int tim; 22 | 23 | void dfs(int s) 24 | { 25 | vis[s] = true; 26 | in[s] = ++tim; 27 | vis_time_vertex[tim] = s; // ET array [Instead for 2*n , IT runs for O(n) time] 28 | 29 | for(auto child : graph[s]) 30 | { 31 | if(vis[child]) 32 | { 33 | continue; 34 | } 35 | dfs(child); 36 | } 37 | out[s] = tim; 38 | } 39 | 40 | 41 | int Tree[4*N]; 42 | 43 | void update(int node ,int lo ,int hi ,int pos ,int val) 44 | { 45 | if(lo==hi) 46 | { 47 | Tree[node] = val; 48 | return; 49 | } 50 | 51 | int mid = (lo+hi)>>1; 52 | 53 | if(pos<=mid) 54 | { 55 | update(node*2 , lo, mid , pos,val); 56 | } 57 | else 58 | { 59 | update(node*2+1 , mid+1 , hi , pos ,val); 60 | } 61 | 62 | Tree[node] = max(Tree[node*2] , Tree[node*2+1]); 63 | } 64 | 65 | 66 | int query(int node, int lo ,int hi,int i,int j) 67 | { 68 | if(hij) 69 | { 70 | return -1; 71 | } 72 | 73 | if(lo>=i && hi <= j) 74 | { 75 | return Tree[node]; 76 | } 77 | 78 | int mid = (lo+hi)>>1; 79 | int x = query(node*2 , lo , mid , i , j); 80 | int y = query(node*2+1 , mid+1 , hi, i, j); 81 | 82 | return max(x,y); 83 | } 84 | 85 | int32_t main() 86 | { 87 | ios::sync_with_stdio(0); 88 | cin.tie(0); 89 | 90 | int n,q; 91 | cin>>n>>q; 92 | vectorv; 93 | 94 | for(int i=0;i>a; 98 | v.push_back(a); 99 | } 100 | 101 | for(int i=0;i>x>>y; 105 | graph[x].push_back(y); 106 | graph[y].push_back(x); 107 | } 108 | 109 | 110 | dfs(1); 111 | 112 | for(int i=1;i<=n;i++) 113 | { 114 | update(1,1,n,i , v[vis_time_vertex[i]-1]); 115 | } 116 | 117 | while(q--) 118 | { 119 | int tt; 120 | cin>>tt; 121 | int node1; 122 | cin>>node1; 123 | vector>p; 124 | 125 | bool flag = false; 126 | 127 | for(int i=0;i>v; 131 | 132 | if(in[v]= out[node1]) 133 | { 134 | flag = true; 135 | } 136 | 137 | if(in[v]>in[node1] && out[v] <= out[node1] ) 138 | { 139 | p.push_back({in[v] , out[v]}); 140 | } 141 | } 142 | 143 | if(flag) 144 | { 145 | cout<<-1< 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace __gnu_pbds; 9 | #define endl "\n" 10 | #define int long long int 11 | #define ordered_set tree< int, null_type, less, rb_tree_tag,tree_order_statistics_node_update> 12 | 13 | 14 | const double eps = 1e-9; 15 | 16 | int Gauss(vector> a, vector &ans) 17 | { 18 | int n = (int)a.size(), m = (int)a[0].size() - 1; 19 | vector pos(m, -1); 20 | double det = 1; 21 | int rank = 0; 22 | 23 | 24 | for (int col = 0, row = 0; col < m && row < n; ++col) 25 | { 26 | int mx = row; 27 | for (int i = row; i < n; i++) 28 | { 29 | if (fabs(a[i][col]) > fabs(a[mx][col])) 30 | { 31 | mx = i; 32 | } 33 | 34 | } 35 | 36 | if (fabs(a[mx][col]) < eps) 37 | { 38 | det = 0; 39 | continue; 40 | } 41 | for (int i = col; i <= m; i++) 42 | { 43 | swap(a[row][i], a[mx][i]); 44 | } 45 | 46 | if (row != mx) 47 | { 48 | det = -det; 49 | } 50 | 51 | det *= a[row][col]; 52 | pos[col] = row; 53 | for (int i = 0; i < n; i++) 54 | { 55 | if (i != row && fabs(a[i][col]) > eps) 56 | { 57 | double c = a[i][col] / a[row][col]; 58 | for (int j = col; j <= m; j++) 59 | { 60 | a[i][j] -= a[row][j] * c; 61 | } 62 | 63 | } 64 | } 65 | ++row; 66 | ++rank; 67 | } 68 | ans.assign(m, 0); 69 | for (int i = 0; i < m; i++) 70 | { 71 | if (pos[i] != -1) 72 | { 73 | ans[i] = a[pos[i]][m] / a[pos[i]][i]; 74 | } 75 | 76 | } 77 | for (int i = 0; i < n; i++) 78 | { 79 | double sum = 0; 80 | for (int j = 0; j < m; j++) 81 | { 82 | sum += ans[j] * a[i][j]; 83 | } 84 | 85 | if (fabs(sum - a[i][m]) > eps) 86 | { 87 | return -1; // no solution 88 | } 89 | 90 | } 91 | for (int i = 0; i < m; i++) 92 | { 93 | if (pos[i] == -1) 94 | { 95 | return 2; // infinte solutions 96 | } 97 | 98 | } 99 | 100 | return 1; // unique solution 101 | } 102 | 103 | 104 | 105 | 106 | int32_t main() 107 | { 108 | ios::sync_with_stdio(0); 109 | cin.tie(0); 110 | 111 | 112 | int n, m; 113 | cin >> n >> m; 114 | 115 | vector> v(n); 116 | for (int i = 0; i < n; i++) 117 | { 118 | for (int j = 0; j <= m; j++) // m-th colunm contain the value of constant 119 | { 120 | double x; 121 | cin >> x; 122 | v[i].push_back(x); 123 | } 124 | } 125 | vector ans; 126 | 127 | int k = Gauss(v, ans); 128 | 129 | if (k) 130 | { 131 | for (int i = 0; i < n; i++) 132 | { 133 | cout << fixed << setprecision(5) << ans[i] << ' '; 134 | } 135 | 136 | } 137 | else 138 | { 139 | cout << "no solution"<node[N]; // it is equal to [[ int node[N][ALPH] ]]; Trie er moto 11 | const int root = 0; 12 | int avail = 0; 13 | 14 | //Suffix Link or Failure Link 15 | int fail[N]; 16 | int nxtWord[N]; 17 | int wordId[N]; 18 | 19 | 20 | void ini() 21 | { 22 | for(int i=0;i<=avail;i++) 23 | { 24 | node[i].clear(); 25 | } 26 | avail = 0; 27 | } 28 | 29 | int insertTrie(const string &s , int idx) 30 | { 31 | int cur = root; 32 | for(int i=0;iq; 56 | for(auto x : node[root]) 57 | { 58 | q.push(x.second); // root er child node er No. 59 | } 60 | while(!q.empty()) 61 | { 62 | int u = q.front(); 63 | q.pop(); 64 | for(auto [ch , v] : node[u]) // v = child node . ch = transition character 65 | { 66 | int f = fail[u]; // parent er fail link e gelam : jate sekan theke check korbo node ch e Transition hoy naki 67 | 68 | while(node[f][ch]==0 && f!=0) // jotokkon porjonto f No. node theke ch Transition exit's na kore totokkon failure link e jump kortei thakbo . f = 0 hoyegele off 69 | { 70 | f = fail[f]; 71 | } 72 | 73 | fail[v] = node[f][ch]; // jodi node[f][ch] ch na thake tahole auto f = 0 zero assign(ie. root ) map er karone 74 | 75 | if(wordId[fail[v]] !=-1) 76 | { 77 | nxtWord[v] = fail[v]; 78 | } 79 | else 80 | { 81 | nxtWord[v] = nxtWord[fail[v]]; 82 | } 83 | 84 | q.push(v); 85 | 86 | } 87 | } 88 | } 89 | 90 | 91 | vector> match(const string &text , int q) 92 | { 93 | vector> ret(q); 94 | 95 | int cur = root; 96 | 97 | for(int i=0;i>t; 127 | 128 | while(t--) 129 | { 130 | ini(); 131 | string text; 132 | cin>>text; 133 | int n; 134 | cin>>n; 135 | vectorid; 136 | for(int i=0;i>s; 140 | id.push_back(insertTrie(s,i)); 141 | } 142 | computeFailureLinkBFS(); 143 | 144 | auto matching = match(text,n); 145 | 146 | for(int i=0;i 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace __gnu_pbds; 9 | #define endl "\n" 10 | #define int long long int 11 | #define ordered_set tree< int, null_type, less, rb_tree_tag,tree_order_statistics_node_update> 12 | 13 | //https://codeforces.com/gym/102625/problem/G 14 | 15 | 16 | //Modified dsu 17 | //dsu + ordered set 18 | // [ u -- v edge] lets say I want to get the size of [left part of u in the component tree and right part of v in the same component tree] 19 | 20 | 21 | const int N = 2e5+100; 22 | vectorgraph[N]; 23 | int in[N]; 24 | int out[N]; 25 | int tim; 26 | 27 | void dfs(int s , int p) 28 | { 29 | in[s] = tim++; 30 | 31 | for(auto child : graph[s]) 32 | { 33 | if(child==p) 34 | { 35 | continue; 36 | } 37 | dfs(child,s); 38 | } 39 | 40 | out[s] = tim; 41 | } 42 | 43 | 44 | int parent[N]; 45 | ordered_set sz[N]; 46 | 47 | void make(int v) 48 | { 49 | parent[v] = v; 50 | sz[v].insert(in[v]); 51 | } 52 | 53 | int Find(int v) 54 | { 55 | if(v==parent[v]) 56 | { 57 | return v; 58 | } 59 | 60 | return v = Find(parent[v]); 61 | } 62 | 63 | void Union(int a,int b) 64 | { 65 | a = Find(a); 66 | b = Find(b); 67 | 68 | if(a!=b) 69 | { 70 | if(sz[a].size() left_right_size(int u,int v) 86 | { 87 | bool flag = false; 88 | if(in[u]>in[v]) 89 | { 90 | flag = true; 91 | swap(u,v); 92 | } // u age dukbe 93 | 94 | u = Find(u); 95 | 96 | int a = sz[u].order_of_key(out[v]) - sz[u].order_of_key(in[v]); // This represent same component e v er subtree size . ba right part er size 97 | int b = sz[u].size()-a ; // this represent the component size of u or left part 98 | 99 | if(flag) 100 | { 101 | return {b,a}; // b hocche u er diker size and a hocche v er diker size 102 | } 103 | else 104 | { 105 | return {a,b}; // a hocce u er diker size and b hocce v er diker size 106 | } 107 | 108 | } 109 | 110 | 111 | int32_t main() 112 | { 113 | ios::sync_with_stdio(0); 114 | cin.tie(0); 115 | 116 | int n; 117 | cin>>n; 118 | 119 | vector>edges; 120 | 121 | sets; 122 | 123 | for(int i=1;i>x>>y>>w; 127 | edges.push_back({i,x,y,w}); 128 | graph[x].push_back(y); 129 | graph[y].push_back(x); 130 | 131 | s.insert(w); 132 | } 133 | 134 | dfs(1,0); 135 | 136 | sort(edges.begin() , edges.end() , [&](auto a, auto b){return a[3]ans(n+1); 148 | 149 | for(auto w : s) 150 | { 151 | int r = l; 152 | 153 | while(r+1res; 179 | 180 | for(int i=1;i 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace __gnu_pbds; 9 | #define endl "\n" 10 | #define int long long int 11 | #define ordered_set tree< int, null_type, less, rb_tree_tag,tree_order_statistics_node_update> 12 | 13 | //https://codeforces.com/gym/102625/problem/G 14 | 15 | 16 | //Modified dsu 17 | //dsu + ordered set 18 | // [ u -- v edge] lets say I want to get the size of [left part of u in the component tree and right part of v in the same component tree] 19 | 20 | 21 | const int N = 2e5+100; 22 | vectorgraph[N]; 23 | int in[N]; 24 | int out[N]; 25 | int tim; 26 | 27 | void dfs(int s , int p) 28 | { 29 | in[s] = tim++; 30 | 31 | for(auto child : graph[s]) 32 | { 33 | if(child==p) 34 | { 35 | continue; 36 | } 37 | dfs(child,s); 38 | } 39 | 40 | out[s] = tim; 41 | } 42 | 43 | 44 | int parent[N]; 45 | ordered_set sz[N]; 46 | 47 | void make(int v) 48 | { 49 | parent[v] = v; 50 | sz[v].insert(in[v]); 51 | } 52 | 53 | int Find(int v) 54 | { 55 | if(v==parent[v]) 56 | { 57 | return v; 58 | } 59 | 60 | return parent[v] = Find(parent[v]); 61 | } 62 | 63 | void Union(int a,int b) 64 | { 65 | a = Find(a); 66 | b = Find(b); 67 | 68 | if(a!=b) 69 | { 70 | if(sz[a].size() left_right_size(int u,int v) 86 | { 87 | bool flag = false; 88 | if(in[u]>in[v]) 89 | { 90 | flag = true; 91 | swap(u,v); 92 | } // u age dukbe 93 | 94 | u = Find(u); 95 | 96 | int a = sz[u].order_of_key(out[v]) - sz[u].order_of_key(in[v]); // This represent same component e v er subtree size . ba right part er size 97 | int b = sz[u].size()-a ; // this represent the component size of u or left part 98 | 99 | if(flag) 100 | { 101 | return {b,a}; // b hocche u er diker size and a hocche v er diker size 102 | } 103 | else 104 | { 105 | return {a,b}; // a hocce u er diker size and b hocce v er diker size 106 | } 107 | 108 | } 109 | 110 | 111 | int32_t main() 112 | { 113 | ios::sync_with_stdio(0); 114 | cin.tie(0); 115 | 116 | int n; 117 | cin>>n; 118 | 119 | vector>edges; 120 | 121 | sets; 122 | 123 | for(int i=1;i>x>>y>>w; 127 | edges.push_back({i,x,y,w}); 128 | graph[x].push_back(y); 129 | graph[y].push_back(x); 130 | 131 | s.insert(w); 132 | } 133 | 134 | dfs(1,0); 135 | 136 | sort(edges.begin() , edges.end() , [&](auto a, auto b){return a[3]ans(n+1); 148 | 149 | for(auto w : s) 150 | { 151 | int r = l; 152 | 153 | while(r+1res; 179 | 180 | for(int i=1;igraph[N]; 7 | vectorRgraph[N]; 8 | vectorforder; 9 | bool vis1[N]; 10 | bool vis2[N]; 11 | int SCC[N]; 12 | vectorassignment(N , false); 13 | 14 | void addedge(int a,int b) 15 | { 16 | graph[a].push_back(b); 17 | } 18 | void addRedge(int a,int b) 19 | { 20 | Rgraph[b].push_back(a); 21 | } 22 | 23 | void dfs1(int s) 24 | { 25 | vis1[s] = true; 26 | for(auto child:graph[s]) 27 | { 28 | if(vis1[child]) 29 | { 30 | continue; 31 | } 32 | dfs1(child); 33 | } 34 | forder.push_back(s); 35 | } 36 | 37 | void dfs2(int s,int sccno) 38 | { 39 | vis2[s] = true; 40 | SCC[s] = sccno; 41 | for(auto child : Rgraph[s]) 42 | { 43 | if(vis2[child]) 44 | { 45 | continue; 46 | } 47 | dfs2(child,sccno); 48 | } 49 | } 50 | 51 | 52 | int32_t main() 53 | { 54 | ios::sync_with_stdio(0); 55 | cin.tie(0); 56 | 57 | int n ;// number of variable 58 | cin>>n; 59 | int m; // number of clause 60 | cin>>m; 61 | 62 | int a[m]; // first element of clause 63 | int b[m]; // second element of clause 64 | 65 | for(int i=0;i>a[i]; 68 | } 69 | for(int i=0;i>b[i]; 72 | } 73 | 74 | for(int i=0;i0 && b[i]> 0) // (a v b) = (-a -> b)^(-b -> a) 77 | { 78 | addedge(a[i]+n , b[i]); // (-a -> b) 79 | addRedge(a[i]+n , b[i]); 80 | addedge(b[i]+n , a[i]); //(-b -> a) 81 | addRedge(b[i]+n , a[i]); 82 | 83 | } 84 | else if(a[i]>0 && b[i]<0) // (a v -b) = (-a -> -b)^(b -> a) 85 | { 86 | addedge(a[i]+n , n-b[i]); // (-a -> -b) 87 | addRedge(a[i]+n , n-b[i]); 88 | addedge(-b[i], a[i]); // (b -> a) 89 | addRedge(-b[i] , a[i]); 90 | } 91 | else if(a[i]<0 && b[i]>0) // (-a v b) = (a -> b)^(-b -> -a) 92 | { 93 | addedge(-a[i] , b[i]); // (a -> b) 94 | addRedge(-a[i] , b[i]); 95 | addedge(b[i]+n, n-a[i]); // (-b -> -a) 96 | addRedge(b[i]+n , n-a[i]); 97 | } 98 | else //(-a v -b) = (a -> -b)^(b -> -a) 99 | { 100 | addedge(-a[i] , n-b[i]); // (a -> -b) 101 | addRedge(-a[i] , n-b[i]); 102 | addedge(-b[i] , n-a[i]); // (b -> -a) 103 | addRedge(-b[i] , n-a[i]); 104 | } 105 | } 106 | 107 | for(int i=1;i<=2*n;i++) 108 | { 109 | if(vis1[i]==false) 110 | { 111 | dfs1(i); 112 | } 113 | } 114 | 115 | reverse(forder.begin(),forder.end()); 116 | int cnt=0; 117 | for(auto x : forder) 118 | { 119 | if(vis2[x]==false) 120 | { 121 | cnt++; 122 | dfs2(x,cnt); 123 | } 124 | } 125 | 126 | 127 | bool ans = true; 128 | 129 | 130 | for(int i=1;i<=n;i++) 131 | { 132 | 133 | if(SCC[i]==SCC[i+n]) 134 | { 135 | ans = false; 136 | } 137 | assignment[i] = SCC[i+n] x) hole x = true else (x -> -x) hole x = false [for testing build a truth table] 138 | } 139 | 140 | 141 | 142 | if(ans==false) 143 | { 144 | cout<<"The given expression is NOT satisfiable."<> graph[N], altered_graph[N]; 17 | 18 | int dist[N]; 19 | int vis[N]; 20 | 21 | void dijkstra(int ss, int V) 22 | { 23 | for (int i = 0; i < V; i++) 24 | { 25 | dist[i] = inf; 26 | vis[i] = false; 27 | } 28 | 29 | dist[ss] = 0; 30 | priority_queue, vector>, greater>> pq; 31 | pq.push({0, ss}); 32 | 33 | while (!pq.empty()) 34 | { 35 | int father = pq.top().second; 36 | pq.pop(); 37 | 38 | if (vis[father]) continue; 39 | vis[father] = true; 40 | 41 | for (auto child : altered_graph[father]) 42 | { 43 | int v = child.first; 44 | int vw = child.second; 45 | if (vis[v]) continue; 46 | if (dist[v] > dist[father] + vw) 47 | { 48 | dist[v] = dist[father] + vw; 49 | pq.push({dist[v], v}); 50 | } 51 | } 52 | } 53 | } 54 | 55 | vector bellmanFord(int V) 56 | { 57 | vector dist(V, inf); 58 | dist[V - 1] = 0; 59 | 60 | for (int i = 0; i < V - 1; i++) 61 | { 62 | for (int u = 0; u < V; u++) 63 | { 64 | for (auto edge : graph[u]) 65 | { 66 | int v = edge.first; 67 | int weight = edge.second; 68 | if (dist[u] != inf && dist[u] + weight < dist[v]) 69 | { 70 | dist[v] = dist[u] + weight; 71 | } 72 | } 73 | } 74 | } 75 | 76 | for (int u = 0; u < V; u++) { 77 | for (auto edge : graph[u]) { 78 | int v = edge.first; 79 | int weight = edge.second; 80 | if (dist[u] != inf && dist[u] + weight < dist[v]) 81 | { 82 | cout << "Negative weight cycle detected!" << endl; 83 | exit(0); 84 | } 85 | } 86 | } 87 | 88 | return dist; 89 | } 90 | 91 | void johnsonAlgorithm(int V) { 92 | for (int i = 0; i < V; i++) 93 | { 94 | graph[V].push_back({i, 0}); 95 | } 96 | 97 | vector h = bellmanFord(V + 1); // The potential function h[] is used to "normalize" the graph by shifting the edge weights in such a way that all edges have non-negative weights 98 | 99 | for (int i = 0; i < V; i++) 100 | { 101 | for (auto& edge : graph[i]) 102 | { 103 | int v = edge.first; 104 | int weight = edge.second; 105 | altered_graph[i].push_back({v, weight + h[i] - h[v]}); 106 | } 107 | } 108 | 109 | for (int u = 0; u < V; u++) 110 | { 111 | cout << "Shortest Distance from vertex " << u << ":"<> input = { 136 | {0, -5, 2, 3}, 137 | {0, 0, 4, 0}, 138 | {0, 0, 0, 1}, 139 | {0, 0, 0, 0} 140 | }; 141 | 142 | for (int i = 0; i < 4; i++) 143 | { 144 | for (int j = 0; j < 4; j++) 145 | { 146 | if (input[i][j] != 0) 147 | { 148 | graph[i].push_back({j, input[i][j]}); 149 | } 150 | } 151 | } 152 | 153 | johnsonAlgorithm(4); 154 | 155 | return 0; 156 | } 157 | -------------------------------------------------------------------------------- /FLOW/Minimum Cost Maximum Flow With Negative Cycle(MCMF).cpp: -------------------------------------------------------------------------------- 1 | // Push-Relabel implementation of the cost-scaling algorithm 2 | // Runs in O( * log(V * max_edge_cost)) = O( V^3 * log(V * C)) 3 | // Really fast in practice, 3e4 edges are fine. 4 | // Operates on integers, costs are multiplied by N!! 5 | 6 | 7 | 8 | 9 | // this is shohage vais code, I didnot understand this ... When I do I will write one. 10 | 11 | #include 12 | using namespace std; 13 | 14 | // source: dacin21 15 | template 16 | struct mcSFlow { 17 | struct Edge { 18 | cost_t c; 19 | flow_t f; 20 | int to, rev; 21 | Edge(int _to, cost_t _c, flow_t _f, int _rev): c(_c), f(_f), to(_to), rev(_rev) {} 22 | }; 23 | static constexpr cost_t INFCOST = numeric_limits::max() / 2; 24 | cost_t eps; 25 | int N, S, T; 26 | vector > G; 27 | vector isq, cur; 28 | vector ex; 29 | vector h; 30 | mcSFlow(int _N, int _S, int _T): eps(0), N(_N), S(_S), T(_T), G(_N) {} 31 | void add_edge(int a, int b, cost_t cost, flow_t cap) { 32 | assert(cap >= 0); 33 | assert(a >= 0 && a < N && b >= 0 && b < N); 34 | if(a == b) { 35 | assert(cost >= 0); 36 | return; 37 | } 38 | cost *= N; 39 | eps = max(eps, abs(cost)); 40 | G[a].emplace_back(b, cost, cap, G[b].size()); 41 | G[b].emplace_back(a, -cost, 0, G[a].size() - 1); 42 | } 43 | void add_flow(Edge& e, flow_t f) { 44 | Edge &back = G[e.to][e.rev]; 45 | if (!ex[e.to] && f) 46 | hs[h[e.to]].push_back(e.to); 47 | e.f -= f; 48 | ex[e.to] += f; 49 | back.f += f; 50 | ex[back.to] -= f; 51 | } 52 | vector > hs; 53 | vector co; 54 | flow_t max_flow() { 55 | ex.assign(N, 0); 56 | h.assign(N, 0); 57 | hs.resize(2 * N); 58 | co.assign(2 * N, 0); 59 | cur.assign(N, 0); 60 | h[S] = N; 61 | ex[T] = 1; 62 | co[0] = N - 1; 63 | for(auto &e : G[S]) add_flow(e, e.f); 64 | if(hs[0].size()) 65 | for (int hi = 0; hi >= 0;) { 66 | int u = hs[hi].back(); 67 | hs[hi].pop_back(); 68 | while (ex[u] > 0) { // discharge u 69 | if (cur[u] == G[u].size()) { 70 | h[u] = 1e9; 71 | for(unsigned int i = 0; i < G[u].size(); ++i) { 72 | auto &e = G[u][i]; 73 | if (e.f && h[u] > h[e.to] + 1) { 74 | h[u] = h[e.to] + 1, cur[u] = i; 75 | } 76 | } 77 | if (++co[h[u]], !--co[hi] && hi < N) 78 | for(int i = 0; i < N; ++i) 79 | if (hi < h[i] && h[i] < N) { 80 | --co[h[i]]; 81 | h[i] = N + 1; 82 | } 83 | hi = h[u]; 84 | } else if (G[u][cur[u]].f && h[u] == h[G[u][cur[u]].to] + 1) 85 | add_flow(G[u][cur[u]], min(ex[u], G[u][cur[u]].f)); 86 | else ++cur[u]; 87 | } 88 | while (hi >= 0 && hs[hi].empty()) --hi; 89 | } 90 | return -ex[S]; 91 | } 92 | void push(Edge &e, flow_t amt) { 93 | if(e.f < amt) amt = e.f; 94 | e.f -= amt; 95 | ex[e.to] += amt; 96 | G[e.to][e.rev].f += amt; 97 | ex[G[e.to][e.rev].to] -= amt; 98 | } 99 | void relabel(int vertex) { 100 | cost_t newHeight = -INFCOST; 101 | for(unsigned int i = 0; i < G[vertex].size(); ++i) { 102 | Edge const&e = G[vertex][i]; 103 | if(e.f && newHeight < h[e.to] - e.c) { 104 | newHeight = h[e.to] - e.c; 105 | cur[vertex] = i; 106 | } 107 | } 108 | h[vertex] = newHeight - eps; 109 | } 110 | static constexpr int scale = 2; 111 | pair minCostMaxFlow() { 112 | cost_t retCost = 0; 113 | for(int i = 0; i < N; ++i) 114 | for(Edge &e : G[i]) 115 | retCost += e.c * (e.f); 116 | //find max-flow 117 | flow_t retFlow = max_flow(); 118 | h.assign(N, 0); 119 | ex.assign(N, 0); 120 | isq.assign(N, 0); 121 | cur.assign(N, 0); 122 | queue q; 123 | for(; eps; eps >>= scale) { 124 | //refine 125 | fill(cur.begin(), cur.end(), 0); 126 | for(int i = 0; i < N; ++i) 127 | for(auto &e : G[i]) 128 | if(h[i] + e.c - h[e.to] < 0 && e.f) push(e, e.f); 129 | for(int i = 0; i < N; ++i) { 130 | if(ex[i] > 0) { 131 | q.push(i); 132 | isq[i] = 1; 133 | } 134 | } 135 | // make flow feasible 136 | while(!q.empty()) { 137 | int u = q.front(); 138 | q.pop(); 139 | isq[u] = 0; 140 | while(ex[u] > 0) { 141 | if(cur[u] == G[u].size()) 142 | relabel(u); 143 | for(unsigned int &i = cur[u], max_i = G[u].size(); i < max_i; ++i) { 144 | Edge &e = G[u][i]; 145 | if(h[u] + e.c - h[e.to] < 0) { 146 | push(e, ex[u]); 147 | if(ex[e.to] > 0 && isq[e.to] == 0) { 148 | q.push(e.to); 149 | isq[e.to] = 1; 150 | } 151 | if(ex[u] == 0) break; 152 | } 153 | } 154 | } 155 | } 156 | if(eps > 1 && eps >> scale == 0) { 157 | eps = 1 << scale; 158 | } 159 | } 160 | for(int i = 0; i < N; ++i) { 161 | for(Edge &e : G[i]) { 162 | retCost -= e.c * (e.f); 163 | } 164 | } 165 | return make_pair(retFlow, retCost / 2 / N); 166 | } 167 | flow_t getFlow(Edge const &e) { 168 | return G[e.to][e.rev].f; 169 | } 170 | }; 171 | -------------------------------------------------------------------------------- /GRAPH/Euler Path_Circuit.cpp: -------------------------------------------------------------------------------- 1 | Euler Path/Circuit : Visit all edges excatly once. 2 | 3 | Hamilton Path/Circuit: Visit all vertex excatly once. 4 | 5 | [Finding hamilton path/circuit is an NP - Complete problem] 6 | 7 | Euler Path/Circuit Undirected: 8 | 1.Euler Circuit: All vertices must have an even degree. 9 | 2.Euler Path: Exactly two vertices must have an odd degree (the path starts at one and ends at the other). 10 | 11 | 12 | Euler Path/Circuit Directed: 13 | 1. Euler Circuit: The graph must be strongly connected, and for every vertex, the in-degree must equal the out-degree. 14 | 15 | 2. Euler Path: The graph must be connected, Exactly one vertex must have out-degree - in-degree = 1 and exactly one vertex must have in-degree - out-degree = 1. All other vertices must have in-degree = out-degree. 16 | 17 | 18 | 19 | 20 | Hierholzer's algorithm For Undirected: 21 | 22 | 23 | // https://www.youtube.com/watch?v=8MpoO2zA2l4 [This video is for directed. But just remember that, instead of removing outdegree by 1, we will remove an edge. See the implementation of how we remove an edge. 24 | // Hierholzer's algorithm 25 | // Euler path/circuit in a undirected graph 26 | 27 | 28 | 29 | 30 | // https://cses.fi/problemset/task/1691 31 | 32 | const int N = 2e5+100; 33 | setgraph[N]; 34 | int degree[N]; 35 | vectorpath; 36 | bool vis[N]; 37 | 38 | void modified_dfs(int s) 39 | { 40 | 41 | while(!graph[s].empty()) // this is just to make sure if out[s], or out_degree of s becomes 0, we add it to path[] or solution, like stated in the heirhozler algoritm. 42 | { 43 | int v = *graph[s].begin(); // For undirected graph, we consider each edge as an out_edge, so we remove it from count, so that we can get out[s] = 0 and add s to path 44 | 45 | graph[s].erase(v); // this is removing [s - v] edge from count 46 | graph[v].erase(s); // this is removing [s - v] edge from count 47 | 48 | modified_dfs(v); 49 | } 50 | 51 | path.push_back(s); 52 | 53 | 54 | } 55 | 56 | int32_t main() 57 | { 58 | ios::sync_with_stdio(0); 59 | cin.tie(0); 60 | 61 | int n,m; 62 | cin>>n>>m; 63 | 64 | for(int i=0;i>a>>b; 68 | graph[a].insert(b); 69 | graph[b].insert(a); 70 | degree[a]++; 71 | degree[b]++; 72 | } 73 | 74 | bool ok = true; 75 | 76 | for(int i=1;i<=n;i++) 77 | { 78 | if(degree[i]%2!=0) 79 | { 80 | ok = false; 81 | break; 82 | } 83 | } 84 | 85 | if(!ok) 86 | { 87 | cout<<"IMPOSSIBLE"<graph[N]; 132 | int in[N]; 133 | int out[N]; 134 | vectorpath; 135 | bool vis[N]; 136 | 137 | void modified_dfs(int s) 138 | { 139 | 140 | while(!graph[s].empty()) // this is just to make sure if out[s], or out_degree of s becomes 0, we add it to path[] or solution, like stated in the heirhozler algoritm 141 | { 142 | int v = graph[s].back(); 143 | graph[s].pop_back(); 144 | modified_dfs(v); 145 | } 146 | 147 | path.push_back(s); 148 | 149 | 150 | } 151 | 152 | int32_t main() 153 | { 154 | ios::sync_with_stdio(0); 155 | cin.tie(0); 156 | 157 | int n,m; 158 | cin>>n>>m; 159 | 160 | for(int i=0;i>a>>b; 164 | graph[a].push_back(b); 165 | out[a]++; 166 | in[b]++; 167 | } 168 | 169 | bool ok = true; 170 | 171 | for(int i=2;i graph[N]; 14 | int level[N]; 15 | int done[N]; // done[u] array is to keep track of which edges have already been tried for a given node during a DFS call. This ensures that we don't revisit the same edges unnecessarily and speeds up the process. 16 | 17 | 18 | // This is for directed, for undirected make sure to include edges in both direction addEdge(u,v,c) and addEdge(v,u,c). 19 | void addEdge(int u, int v, int capacity, int id = -1) 20 | { 21 | graph[u].push_back({v, (int)graph[v].size(), capacity, id}); 22 | graph[v].push_back({u, (int)graph[u].size()-1, 0, -id}); 23 | } 24 | 25 | 26 | // BFS to build Level Graph 27 | bool bfs(int source, int sink) 28 | { 29 | fill(level, level+N, -1); 30 | level[source] = 0; 31 | queueq; 32 | q.push(source); 33 | 34 | while(!q.empty()) 35 | { 36 | int u = q.front(); 37 | q.pop(); 38 | 39 | for(auto &[v, rev, residual_capacity, id]: graph[u]) 40 | { 41 | if(level[v] != -1 || residual_capacity == 0) 42 | { 43 | continue; 44 | } 45 | 46 | level[v] = level[u] + 1; 47 | q.push(v); 48 | } 49 | } 50 | 51 | return level[sink] != -1; // sink is reachable = true 52 | } 53 | 54 | 55 | // DFS to send flow along augmenting paths 56 | int dfs(int u, int sink, int flow) 57 | { 58 | if(u == sink) 59 | { 60 | return flow; 61 | } 62 | 63 | for(; done[u] < graph[u].size(); done[u]++) 64 | { 65 | auto &[v, rev, residual_capacity, id] = graph[u][done[u]]; 66 | 67 | if(level[v] == level[u]+1 && residual_capacity > 0) // only traversing trough level graph 68 | { 69 | int pathFlow = min(flow, residual_capacity); 70 | int pushedFlow = dfs(v, sink, pathFlow); 71 | 72 | if(pushedFlow > 0) 73 | { 74 | residual_capacity -= pushedFlow; 75 | graph[v][rev].residual_capacity += pushedFlow; 76 | 77 | return pushedFlow; 78 | } 79 | } 80 | } 81 | 82 | return 0; 83 | } 84 | 85 | 86 | int Dinic(int source, int sink) 87 | { 88 | int max_flow = 0; 89 | 90 | while(bfs(source, sink)) // build the level graph 91 | { 92 | fill(done, done+N, 0); 93 | 94 | while(true) // traverse on the same level graph multiple time, which is efficiant than Edmonds-Karp. As we are blocking multiple edges(residual_capacity = 0) using the same level graph. 95 | { 96 | int flow = dfs(source, sink, inf); 97 | 98 | if(flow == 0) 99 | { 100 | break; 101 | } 102 | 103 | max_flow += flow; 104 | } 105 | 106 | } 107 | 108 | return max_flow; 109 | } 110 | 111 | 112 | 113 | // For minimum cut, edges on minimum cut will have residual capacity = 0. 114 | // So if we run a BFS from source and reach vertices through edges that still have residual capacity > 0. We will eventually stop after finding residual capacity = 0 edges. 115 | // Now visited ones are Vs and unvisited once are Vt in a minimum cut X = (Vs, Vt), where Vs includes source and Vt includes sink. 116 | 117 | 118 | // Finds all reachable nodes from the source in the residual graph after dinic is called 119 | void FindReachable_BFS(int source, vector &visited) 120 | { 121 | queueq; 122 | q.push(source); 123 | visited[source] = true; 124 | 125 | while(!q.empty()) 126 | { 127 | int u = q.front(); 128 | q.pop(); 129 | 130 | for(auto &[v, rev, residual_capacity, id]: graph[u]) 131 | { 132 | if(visited[v] == true || residual_capacity == 0) 133 | { 134 | continue; 135 | } 136 | 137 | visited[v] = true; 138 | q.push(v); 139 | } 140 | } 141 | } 142 | 143 | vector> FindMinCut(int source, int sink) 144 | { 145 | vector visited(N, false); 146 | 147 | FindReachable_BFS(source, visited); 148 | 149 | vector> Edges; 150 | 151 | for(int u=1; u < N; u++) 152 | { 153 | if(visited[u]) 154 | { 155 | for(auto &[v, rev, residual_capacity, id]: graph[u]) 156 | { 157 | if(visited[v] == false && residual_capacity == 0) 158 | { 159 | Edges.push_back({u,v}); 160 | } 161 | } 162 | } 163 | } 164 | 165 | return Edges; 166 | } 167 | 168 | 169 | 170 | int32_t main() 171 | { 172 | ios::sync_with_stdio(0); 173 | cin.tie(0); 174 | 175 | int n,m; 176 | cin>>n>>m; 177 | 178 | map, bool> mp; 179 | 180 | for(int i=0;i>u>>v; 184 | 185 | mp[{u,v}] = true; 186 | 187 | addEdge(u,v,1); 188 | addEdge(v,u,1); // the problem is for undirected 189 | } 190 | 191 | cout<> Cut_edges = FindMinCut(1, n); 194 | 195 | 196 | set>ans; // Since this is a undirected flow network, we need to remove all the duplicates , and only consider edges like input 197 | 198 | for(auto x : Cut_edges) 199 | { 200 | if(mp[{x.first, x.second}]) 201 | { 202 | ans.insert({x.first, x.second}); 203 | } 204 | else 205 | { 206 | ans.insert({x.second, x.first}); 207 | } 208 | } 209 | 210 | 211 | for(auto x : ans) 212 | { 213 | cout< 2 e ekti edge directed , then er information store hobe cnt[2] Te ::::::::::: ebong 2 = node[1][] is like 1 = parent[2] er moto in directed tree :: age amra parent diye jump kortm : Now children diye jump] 7 | int root = 0; //which means Edge info is actually stored in the 2nd child : and edges er characterictistics is (2 = node[1][]) refers to (1) ---> (2) edge 8 | int avail = 0; 9 | int cnt[N]; 10 | 11 | 12 | void ini() 13 | { 14 | root = 0; 15 | avail = 0; 16 | for(int i=0;i=0;i--) // MSB must be at the top 1 28 | { 29 | if(x &(1<=0;i--) // MSB must be at the top 1 60 | { 61 | if(x &(1<=0;i--) // MSB must be at the top 1 79 | { 80 | if(x&(1<0) // ei edge er info is being stored in cur = node[cur][0] 83 | { 84 | ans |= (1<0) 96 | { 97 | ans |= (1<=0;i--) 117 | { 118 | if(x&(1<0) 121 | { 122 | cur = node[cur][1]; 123 | } 124 | else 125 | { 126 | ans |=(1<0) 134 | { 135 | cur = node[cur][0]; 136 | } 137 | else 138 | { 139 | ans |=(1<=2 156 | cin>>n; 157 | 158 | vectorv; 159 | 160 | ini(); 161 | 162 | //Insert(0); // IN some problem you might need to use this where you have the choice of choosing any number of element : i.e n==1 is allowed 163 | 164 | for(int i=0;i>a; 168 | v.push_back(a); 169 | Insert(a); 170 | } 171 | 172 | int mx = 0; 173 | 174 | for(int i=0;i 2 e ekti edge directed , then er information store hobe cnt[2] Te ::::::::::: ebong 2 = node[1][] is like 1 = parent[2] er moto in directed tree :: age amra parent diye jump kortm : Now children diye jump] 7 | int root = 0; //which means Edge info is actually stored in the 2nd child : and edges er characterictistics is (2 = node[1][]) refers to (1) ---> (2) edge 8 | int avail = 0; 9 | int cnt[N]; 10 | 11 | 12 | void ini() 13 | { 14 | root = 0; 15 | avail = 0; 16 | for(int i=0;i=0;i--) // MSB must be at the top 1 28 | { 29 | if(x &(1<=0;i--) // MSB must be at the top 1 60 | { 61 | if(x &(1<=0;i--) // MSB must be at the top 1 79 | { 80 | if(x&(1<0) // ei edge er info is being stored in cur = node[cur][0] 83 | { 84 | ans |= (1<0) 96 | { 97 | ans |= (1<=0;i--) 117 | { 118 | if(x&(1<0) 121 | { 122 | cur = node[cur][1]; 123 | } 124 | else 125 | { 126 | ans |=(1<0) 134 | { 135 | cur = node[cur][0]; 136 | } 137 | else 138 | { 139 | ans |=(1<=2 156 | cin>>n; 157 | 158 | vectorv; 159 | 160 | ini(); 161 | 162 | //Insert(0); // IN some problem you might need to use this where you have the choice of choosing any number of element : i.e n==1 is allowed 163 | 164 | for(int i=0;i>a; 168 | v.push_back(a); 169 | Insert(a); 170 | } 171 | 172 | int mx = 0; 173 | 174 | for(int i=0;igraph[N]; 7 | int level[N]; 8 | 9 | 10 | 11 | 12 | //LCA Part 13 | const int L = log2(N); 14 | int lca_din[N]; 15 | int lca_dout[N]; 16 | int up[N][L+1]; 17 | int tim_lca; 18 | 19 | 20 | 21 | 22 | 23 | //SEGMENT Tree Part 24 | int n; // to be taken input as no of vertex 25 | 26 | int Tree[2*N] ; 27 | int ara[N]; 28 | int tin[N]; 29 | int tout[N]; 30 | int vis_tim_vertex[N]; 31 | int nxt[N]; 32 | int subtree[N]; 33 | int tim; 34 | 35 | 36 | void dfs(int s, int par) 37 | { 38 | lca_din[s] = tim_lca++; 39 | 40 | up[s][0] = par; 41 | 42 | for(int i=1;i<=L;i++) 43 | { 44 | up[s][i] = up[up[s][i-1]][i-1]; 45 | } 46 | 47 | for(auto child : graph[s]) 48 | { 49 | if(child == par) 50 | { 51 | continue; 52 | } 53 | 54 | dfs(child, s); 55 | } 56 | 57 | lca_dout[s] = tim_lca; 58 | } 59 | 60 | bool is_ancestor(int u, int v) 61 | { 62 | return (lca_din[u] <= lca_din[v] && lca_dout[u] >= lca_dout[v]); 63 | } 64 | 65 | 66 | int lca(int u, int v) 67 | { 68 | if(is_ancestor(u,v)) 69 | { 70 | return v; 71 | } 72 | 73 | if(is_ancestor(v,u)) 74 | { 75 | return v; 76 | } 77 | 78 | for(int i=L;i>=0;i--) 79 | { 80 | if(!is_ancestor(up[u][i], v)) 81 | { 82 | u = up[u][i]; 83 | } 84 | } 85 | 86 | u = up[u][0]; 87 | 88 | return u; 89 | } 90 | 91 | 92 | void dfs1(int s, int par) 93 | { 94 | subtree[s] = 1; 95 | 96 | for(auto &child: graph[s]) 97 | { 98 | if(child == par) 99 | { 100 | continue; 101 | } 102 | 103 | dfs1(child, s); 104 | 105 | subtree[s] += subtree[child]; 106 | 107 | 108 | if(subtree[child] > subtree[graph[s][0]]) 109 | { 110 | swap(child, graph[s][0]); 111 | } 112 | } 113 | 114 | 115 | } 116 | 117 | 118 | void dfs_hld(int s, int par) 119 | { 120 | tin[s] = ++tim; 121 | 122 | vis_tim_vertex[tim] = s; 123 | 124 | for(auto child : graph[s]) 125 | { 126 | if(child == par) 127 | { 128 | continue; 129 | } 130 | 131 | 132 | if(child == graph[s][0]) 133 | { 134 | nxt[child] = nxt[s]; 135 | } 136 | else 137 | { 138 | nxt[child] = child; 139 | } 140 | 141 | dfs_hld(child, s); 142 | } 143 | 144 | tout[s] = tim; 145 | 146 | } 147 | 148 | 149 | // Iterative Segment Tree 150 | 151 | 152 | void build() 153 | { 154 | for(int i=1;i<=n;i++) 155 | { 156 | Tree[n+i-1] = ara[vis_tim_vertex[i]]; 157 | } 158 | for(int i=n-1;i>=1;i--) 159 | { 160 | Tree[i] = max(Tree[i<<1], Tree[i<<1|1]); 161 | } 162 | } 163 | 164 | 165 | 166 | 167 | void update(int pos, int val) 168 | { 169 | pos = pos + n - 1; 170 | Tree[pos] = val; 171 | for(pos >>= 1; pos >= 1; pos >>= 1) 172 | { 173 | Tree[pos] = max(Tree[pos<<1], Tree[pos<<1|1]); 174 | } 175 | } 176 | 177 | 178 | 179 | int query(int l, int r) 180 | { 181 | int res = 0; 182 | l = l + n - 1; 183 | r = r + n - 1; 184 | while(l <= r) 185 | { 186 | if(l & 1) res = max(res, Tree[l++]); 187 | if(!(r & 1)) res = max(res, Tree[r--]); 188 | l >>= 1; 189 | r >>= 1; 190 | } 191 | return res; 192 | } 193 | 194 | 195 | 196 | 197 | int query_up(int l, int u) 198 | { 199 | int res=0; 200 | 201 | while(nxt[u]!=nxt[l]) 202 | { 203 | 204 | res = max(res, query(tin[nxt[u]], tin[u])); 205 | 206 | u = up[nxt[u]][0]; 207 | } 208 | 209 | res = max(res, query(tin[l], tin[u])); 210 | 211 | return res; 212 | } 213 | 214 | 215 | int maximum_query_hld(int u, int v) 216 | { 217 | if(is_ancestor(u,v)) 218 | { 219 | return query_up(u,v); 220 | } 221 | if(is_ancestor(v,u)) 222 | { 223 | return query_up(v,u); 224 | } 225 | 226 | int l = lca(u,v); 227 | 228 | int x = query_up(l,u); 229 | int y = query_up(l,v); 230 | 231 | return max(x,y); 232 | } 233 | 234 | 235 | void update_up(int u,int x) 236 | { 237 | 238 | update(tin[u], x); 239 | } 240 | 241 | 242 | 243 | void HLD() 244 | { 245 | 246 | dfs(1,1); 247 | 248 | 249 | dfs1(1,1); 250 | 251 | 252 | dfs_hld(1,1); 253 | } 254 | 255 | 256 | 257 | 258 | 259 | int32_t main() 260 | { 261 | ios::sync_with_stdio(0); 262 | cin.tie(0); 263 | 264 | int m; 265 | cin>>n>>m; 266 | 267 | for(int i=1;i<=n;i++) 268 | { 269 | cin>>ara[i]; 270 | } 271 | 272 | for(int i=0;i>x>>y; 276 | graph[x].push_back(y); 277 | graph[y].push_back(x); 278 | } 279 | 280 | HLD(); 281 | 282 | build(); 283 | 284 | while(m--) 285 | { 286 | int a; 287 | cin>>a; 288 | if(a == 1) 289 | { 290 | int s,x; 291 | cin>>s>>x; 292 | 293 | update_up(s,x); 294 | } 295 | else 296 | { 297 | int a,b; 298 | cin>>a>>b; 299 | cout< &mp, int k, int add) 91 | { 92 | mp[add]++; 93 | bool ok = mp.size() <= k; 94 | mp[add]--; 95 | if (mp[add] == 0) 96 | { 97 | mp.erase(add); 98 | } 99 | return ok; 100 | } 101 | 102 | int subArrayWithAtmostK(vector &nums, int k) 103 | { 104 | int j = 0; 105 | int ans = 0; 106 | unordered_map mp; 107 | 108 | mp[nums[j]]++; 109 | 110 | for (int i = 0; i < nums.size(); i++) 111 | { 112 | while (j + 1 < nums.size() && isValid(mp, k, nums[j + 1])) 113 | { 114 | mp[nums[j + 1]]++; 115 | j++; // j porjont neya [j included] 116 | } 117 | 118 | if (mp.size() <= k) 119 | { 120 | ans += j - i + 1; // j included. 121 | } 122 | 123 | mp[nums[i]]--; 124 | if (mp[nums[i]] == 0) 125 | { 126 | mp.erase(nums[i]); 127 | } 128 | } 129 | 130 | return ans; 131 | } 132 | int subarraysWithKDistinct(vector &nums, int k) 133 | { 134 | return subArrayWithAtmostK(nums, k) - subArrayWithAtmostK(nums, k - 1); 135 | 136 | // Sub Array With excatly K different integers = Sub Array With AtMost K different integers - Sub Array With AtMost (K-1) different integers 137 | } 138 | }; 139 | 140 | 141 | ===================== Variable length Sliding Window ============== Examples problem(Sub-Array Counting : excalty k property) 142 | 143 | https://leetcode.com/problems/count-number-of-nice-subarrays/?envType=list&envId=p96cfcjg 144 | 145 | class Solution 146 | { 147 | public: 148 | bool isValid(int odd, int k, int num) 149 | { 150 | odd += (num & 1); 151 | return odd <= k; 152 | } 153 | int atMostK(vector &nums, int k) 154 | { 155 | int j = 0; 156 | int ans = 0; 157 | int odd = (nums[0] & 1); 158 | for (int i = 0; i < nums.size(); i++) 159 | { 160 | while (j + 1 < nums.size() && isValid(odd, k, nums[j + 1])) 161 | { 162 | j++; 163 | odd += (nums[j] & 1); // j included . which means j porjonto 164 | } 165 | 166 | if (odd <= k) 167 | { 168 | ans += j - i + 1; // j included 169 | } 170 | 171 | odd -= (nums[i] & 1); 172 | } 173 | 174 | return ans; 175 | } 176 | 177 | int numberOfSubarrays(vector &nums, int k) 178 | { 179 | return atMostK(nums, k) - atMostK(nums, k - 1); //= Excatly k 180 | } 181 | }; 182 | 183 | 184 | -------------------------------------------------------------------------------- /DATA STRUCTURES/Wavelet Tree.cpp: -------------------------------------------------------------------------------- 1 | 2 | // https://www.spoj.com/problems/MKTHNUM/en/ 3 | 4 | 5 | 6 | 7 | /* 8 | 9 | =============================== 10 | Applications of Wavelet Tree 11 | =============================== 12 | 13 | 1. Range k-th smallest element 14 | - Query the k-th smallest (or largest) in subarray [L, R]. 15 | - Example: query_kth(L, R, k) 16 | - Time: O(log σ) 17 | 18 | 2. Range Frequency Query 19 | - Count how many times a value K occurs in [L, R]. 20 | - Example: query_count(L, R, K) 21 | - Time: O(log σ) 22 | 23 | 3. Count of elements ≤ K (or <, >, ≥) 24 | - Count how many numbers in [L, R] are ≤ K. 25 | - Example: query_LTE(L, R, K) 26 | - Time: O(log σ) 27 | 28 | */ 29 | 30 | 31 | 32 | const int N = 1e5 + 100; 33 | const int Maximum = 1e5 + 100; 34 | 35 | 36 | // Increased size to handle N * log(Max) elements 37 | const int Nodes = 4000005; 38 | 39 | struct WaveletTree 40 | { 41 | int Tree[Nodes]; 42 | 43 | int Left[Nodes]; 44 | 45 | int left_child[Nodes]; 46 | int right_child[Nodes]; 47 | 48 | int start_idx[Nodes]; 49 | int end_idx[Nodes]; 50 | 51 | int node_counter = 1; 52 | int array_ptr = 0; 53 | 54 | int mn_val, mx_val; 55 | int n; 56 | int input_arr[N]; 57 | 58 | void build_impl(int parent_mid_val , bool is_left, int parent_node , int node , int low , int high) 59 | { 60 | start_idx[node] = ++array_ptr; 61 | 62 | end_idx[node] = array_ptr - 1; 63 | 64 | int mid = (low + high) >> 1; 65 | 66 | int iter_start = (node == 1)? 1: start_idx[parent_node]; 67 | int iter_end = (node == 1)? n : end_idx[parent_node]; 68 | 69 | for(int i = iter_start; i <= iter_end; i++) 70 | { 71 | int val = (node == 1)? input_arr[i] : Tree[i]; 72 | 73 | bool belongs = (node == 1) || (is_left && val <= parent_mid_val) || (!is_left && val > parent_mid_val); 74 | 75 | if(belongs) 76 | { 77 | Tree[array_ptr] = val; 78 | end_idx[node] = array_ptr; 79 | 80 | // Left[i] stores count of elements going left up to index i 81 | Left[array_ptr] = Left[array_ptr - 1] + (val <= mid); 82 | array_ptr++; 83 | } 84 | } 85 | 86 | if(low == high) 87 | { 88 | return; 89 | } 90 | 91 | int count_in_node = end_idx[node] - start_idx[node] + 1; 92 | 93 | int left_elements = Left[end_idx[node]] - Left[start_idx[node] - 1]; 94 | 95 | if(left_elements > 0) 96 | { 97 | left_child[node] = ++node_counter; 98 | build_impl(mid, true, node, left_child[node], low, mid); 99 | } 100 | 101 | if(count_in_node - left_elements > 0) 102 | { 103 | right_child[node] = ++node_counter; 104 | 105 | build_impl(mid, false, node, right_child[node], mid + 1, high); 106 | } 107 | } 108 | 109 | void init(int count , vector &v) 110 | { 111 | n = count; 112 | for(int i = 0; i < n; i++) 113 | { 114 | input_arr[i+1] = v[i]; 115 | } 116 | 117 | node_counter = 1; 118 | array_ptr = 0; 119 | mn_val = 0; 120 | mx_val = Maximum; 121 | 122 | Left[0] = 0; 123 | 124 | build_impl(-1, true, -1, 1, mn_val, mx_val); 125 | } 126 | 127 | 128 | 129 | // Find K-th smallest number in range [L, R] 130 | int query_kth(int L, int R , int k , int node = 1, int low = 0, int high = Maximum) 131 | { 132 | if(low == high) 133 | { 134 | return low; 135 | } 136 | 137 | int mid = (low + high) >> 1; 138 | 139 | int cnt_left = Left[start_idx[node] + R] - Left[start_idx[node] + L - 1]; 140 | 141 | int elements_to_left_before_L = Left[start_idx[node] + L - 1]; 142 | 143 | 144 | int elements_to_left_upto_R = Left[start_idx[node] + R]; 145 | 146 | 147 | if(cnt_left >= k) 148 | { 149 | return query_kth(elements_to_left_before_L, elements_to_left_upto_R - 1, k, left_child[node], low, mid); 150 | } 151 | else 152 | { 153 | int new_L = L - elements_to_left_before_L; 154 | 155 | int new_R = R - elements_to_left_upto_R; 156 | 157 | return query_kth(new_L, new_R, k - cnt_left, right_child[node], mid + 1, high); 158 | } 159 | } 160 | 161 | 162 | 163 | 164 | // Count occurrences of number K in range [L, R] 165 | int query_count(int L , int R, int k , int node = 1, int low = 0, int high = Maximum) 166 | { 167 | if(low == high) 168 | { 169 | return Left[start_idx[node] + R] - Left[start_idx[node] + L - 1]; 170 | } 171 | 172 | int mid = (low + high) >> 1; 173 | 174 | int elements_to_left_before_L = Left[start_idx[node] + L - 1]; 175 | 176 | int elements_to_left_upto_R = Left[start_idx[node] + R]; 177 | 178 | if(k <= mid) 179 | { 180 | return query_count(elements_to_left_before_L, elements_to_left_upto_R - 1, k, left_child[node], low, mid); 181 | } 182 | else 183 | { 184 | int new_L = L - elements_to_left_before_L; 185 | 186 | int new_R = R - elements_to_left_upto_R; 187 | return query_count(new_L, new_R, k, right_child[node], mid + 1, high); 188 | } 189 | } 190 | 191 | 192 | 193 | // Count numbers Less Than or Equal (LTE) to K in range [L, R] 194 | int query_LTE(int L, int R, int k, int node = 1, int low = 0, int high = Maximum) 195 | { 196 | if(L > R || k < low) 197 | { 198 | return 0; 199 | } 200 | if(high <= k) 201 | { 202 | return R - L + 1; 203 | } 204 | 205 | int mid = (low + high) >> 1; 206 | int elements_to_left_before_L = Left[start_idx[node] + L - 1]; 207 | 208 | int elements_to_left_upto_R = Left[start_idx[node] + R]; 209 | 210 | return query_LTE(elements_to_left_before_L, elements_to_left_upto_R - 1, k, left_child[node], low, mid) + query_LTE(L - elements_to_left_before_L, R - elements_to_left_upto_R, k, right_child[node], mid + 1, high); 211 | } 212 | 213 | } wt; 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | mapidx; 224 | mapridx; 225 | 226 | int32_t main() 227 | { 228 | ios::sync_with_stdio(0); 229 | cin.tie(0); 230 | 231 | int n; 232 | cin>>n; 233 | 234 | int q; 235 | cin>>q; 236 | 237 | vectorv; 238 | 239 | for(int i=0;i>a; 243 | v.push_back(a); 244 | } 245 | 246 | vectorv1; 247 | 248 | v1 = v; 249 | 250 | sort(v1.begin(),v1.end()); 251 | 252 | for(int i=0;i>l>>r>>k; 270 | 271 | l--; 272 | r--; 273 | 274 | int take = wt.query_kth(l,r,k); 275 | 276 | cout< 9 | 10 | **Flow:** The value of the flow of a network **f**, denoted **|f|**, is the total flow going from the source **s**, which is equal to the total flow coming into the sink **t**. 11 | 12 | 13 | 14 |
15 | 16 | **Maximum Flow:** The maximum flow problem involves finding the maximum flow from the source **s** to the sink **t** in a flow network **N**. 17 | 18 | 19 | 20 |
21 | 22 | --- 23 | 24 | **Cut:** A cut of a flow network **N** is a partition of vertices **X = (Vs, Vt)**, where **Vs** is the set of vertices that includes the source **s**, and **Vt** is the set of vertices that includes the destination **t**. 25 | 26 | 27 | 28 | **Forward edge of a cut X:** Origin in **Vs** and destination in **Vt**. 29 | **Backward edge of a cut X:** Origin in **Vt** and destination in **Vs**. 30 | 31 |
32 | 33 | **Capacity of a cut C(X):** Total capacity of forward edges. 34 | 35 |
36 | 37 | **Flow of a cut f(X):** Total flow of forward edges minus the total flow of backward edges. 38 | 39 | --- 40 |
41 | 42 | **Theorem:** The flow value across the network **N**, **|f|**, is equal to the flow of any cut **f(X)**. 43 | 44 |
45 | 46 | **Theorem:** The value of any flow (flow of a cut or the entire network) is less than or equal to the capacity of any cut. 47 | 48 | 49 | 50 | --- 51 | 52 | **Minimum Cut:** A minimum cut is the cut whose capacity is the smallest among all possible cuts. 53 | 54 |
55 | 56 | In a graph, there can be multiple minimum cuts. 57 | 58 |
59 | 60 | **Theorem (Max-Flow Min-Cut):** The value of the maximum flow is equal to the capacity of the minimum cut. 61 | 62 | 63 | For example in this graph max flow = minimum cut = 23. 64 | 65 |
66 |
67 | 68 | **If we can find the capacity of the minimum cut, then we have found the maximum flow. However, finding the capacity of the minimum cut is more difficult than finding the maximum flow using max flow algorithms.** 69 | 70 | --- 71 | 72 | **Residual capacity of edge and path:** 73 | 74 | **Residual Capacity (RC) of edges:** 75 | 76 | - **RC of a edge $\textbf{e}$, in forward direction from $\textbf{u}$ to $\textbf{v}$:** 77 | $\Delta f(\textbf{u}, \textbf{v}) = c(\textbf{e}) - f(\textbf{e})$ 78 | (This is the capacity of the edge minus the flow of the edge.) 79 | 80 | - **RC of a edge $\textbf{e}$ in reverse direction from $\textbf{v}$ to $\textbf{u}$:** 81 | $\Delta f(\textbf{v}, \textbf{u}) = f(\textbf{e})$ 82 | (This is the flow of the edge in forward direction. why do we consider edges in reverse direction? explained below) 83 | 84 |
85 | 86 | **Residual Capacity of a path from source to destination:** 87 | Let $\pi$ be a path from $\textbf{s}$ to $\textbf{t}$. The residual capacity $\Delta f(\pi)$ of $\pi$ is the smallest of the residual capacities of the edges in $\pi$. 88 | 89 | 90 | 91 |
92 | 93 | **Augmenting Path:** 94 | 95 | 96 | 97 |
98 | 99 | **Residual Network:** If we replace the flow/capacity of the edges with the residual capacity of the edges, then the flow network we get is called the residual network. 100 | 101 | 102 | 103 |
104 | 105 | --- 106 | 107 |
108 | 109 | ## Flow Augmentation: 110 | 111 | **Flow Augmentation:** This is the key iteration in all flow algorithms when finding the maximum flow. 112 | 113 | While running the max flow algorithm, in each DFS or BFS iteration, it involves increasing the flow along an augmenting path. 114 | 115 | 116 | 117 |
118 | 119 | **Flow augmentation involves:** 120 | **Forward edges:** Increasing the flow of each edge by the amount of the residual capacity of the augmenting path. (In residual graph, decreasing residual capacity of edges, by the amount of the residual capacity of the augmenting path. (which is normally done in algorithms implementations). 121 | 122 | **Backward edges:** Decreasing the flow of each edge by the amount of the residual capacity of the augmenting path (you can consider this as cancelling or undoing flow of forward edge). (In residual graph, increasing residual capacity of edges, by the amount of the residual capacity of the augmenting path. (which is normally done in algorithms implementations). 123 | 124 | 125 | 126 |
127 | 128 | **Example of flow augmentation:** 129 |
130 | 131 | 132 | 133 | Here **w -> v** is a backward edge. Or edge in reverse direction. 134 | 135 |
136 | 137 | --- 138 | 139 | ## Why decrease backward edges flow? (this is a very crucial to understand): 140 | 141 | Let’s say the current flow considered is: 142 | 143 | 144 | 145 | By direct observation, if we don't undo **v → w** flow **5** and consider flow **5** towards **v → t**, there is no way to increase the max flow of the network. 146 | 147 |
148 | 149 | OK!!, let’s consider an augmenting path in the flow **s → u → w → v → t**. 150 | 151 | 152 | 153 | Look at the **w → v** edge. It is reversed, i.e., **v → w** exists but not **w → v**. But we have to consider **w → v** because there might be the possibility of undoing **v → w** flow. How? Let’s look. 154 | 155 |
156 | 157 | If we perform flow augmentation along **s → u → w → v → t**, the network becomes: 158 | 159 | 160 | 161 | Previously, **s → v** flow was **5**, which went through **v → w** and then **w → t**. Now **v → w** is **0**, and **v → t** is **5**. 162 | 163 |
164 | 165 | Now the question is: does this mean a flow is happening in this path **s → u → w → v → t**? The answer is NO. What actually happened was, initially, we considered flow **s → v → w → t**, but it blocked any flow in **s → u →** direction. 166 | 167 |
168 | 169 | So, we needed to cancel out or undo **v → w** flow, which we did by considering **w → v** along **s → u → w → v → t**. 170 | 171 |
172 | 173 | Thus, the flow is actually happening along **s → v → t (5)** and **s → u → w → t (5)**. 174 | 175 | 176 | --- 177 | 178 |
179 | 180 | **If we don’t consider flow undoing (sending flow through reverse edges), we would have to find an algorithm that always chooses augmenting paths intelligently. This is an NP-Hard problem.** 181 | 182 |
183 | 184 | **However, if we consider flow undoing (sending flow through reverse edges), we can arbitrarily choose any augmenting path without worry. Because if the current path was not ideal, in later iterations, we can undo the flow of edges.** 185 | 186 |
187 | 188 | This is exactly what max flow algorithms do, which is why they have polynomial complexity. 189 | 190 | --- 191 | 192 | ### So, For max flow algorithms, we add a reverse edge for each edge to acheive flow undoing.** 193 | 194 | 195 | 196 |
197 | 198 | 199 | **For max flow algorithms:** 200 | 201 |
202 | 203 | **Capacity of edge:** Equal to the capacity of the edge. 204 |
205 | 206 | **Capacity of reverse edge:** Equal to the flow of the edge (in forward direction). **(Why? Because that is the maximum amount of flow we can cancel or undo for this edge.)** 207 | 208 |
209 | 210 | --- 211 | 212 | # Now you are ready for flow algorithms, you know all basic terminologies 213 | 214 | ## Pathway: 215 | 216 | 1. **Max flow Ford-Fulkerson (O(E * maxflow))** 217 | 2. **Max flow Edmond-karp (O(V * E^2))** 218 | 3. **Max flow Dinics (O(V^2*E)) preferred to use.** 219 | 4. **Minimum cut with dinics (O(V^2*E))** 220 | 5. **Maximum bipartite matching with dinics for learning (O(V^2*E))** 221 | 6. **Maximum bipartite matching hopcraft-karp (O(E * √V)) for use.** 222 | 7. **Minimum cost Maximum Flow using Dijkstra, without negative cycle (O(min(E^2 * V log V, E log V * flow)))** 223 | 8. **Minimum Weighted Maximum Bipartite Matching using MCMF ([O(min(E^2 * V log V, E log V * flow)))** 224 | 9. **Weighted Maximum Bipartite Matching Hungarian (O(V^3))** 225 | 10. **Vertex Cover & Independent Set topic learning.** 226 | 11. **Minimum Vertex Cover/Maximum Independent Set in a Bipartite graph using hopcroft-karp (O(E * √V))** 227 | --------------------------------------------------------------------------------