bool cycleCheck(vector<int>adj[],int node,vector<int>&color)
{
bool check = 0;
color[node]=1;
for(auto ch:adj[node])
{
if(color[ch]==0)
{
check |= cycleCheck(adj,ch,color);
}
else if(color[ch]==1)
{
check = 1;
}
}
color[node]=2;
return check;
}
int main()
{
vector<int>color(v,0);
bool check = 0;
for(int i=0;i<v;i++)
{
if(color[i]==0)
{
check |= cycleCheck(adj,i,color);
}
}
//Check 1 then cycle.
//check 0 then not cycle.
}
Uses the concept that if TOPOLIGICAL sort is possible then no cycle else cycle.
Logic : Try to find the topological sort of the graph if it is possible then no cycle else cycle. So, create a indegree array and push all the nodes with indegree 0 in the queue and then pop the node and reduce the indegree of the child nodes and push the child nodes with indegree 0 in the queue and repeat the process until the queue is empty.
bool isCyclic(int V, vector<int> adj[]) {
vector<int>indegree(V,0);
for(int i=0;i<V;i++)
{
for(auto ch:adj[i])
{
indegree[ch]++;
}
}
queue<int>Q;
for(int i=0;i<V;i++)
{
if(indegree[i]==0){
Q.push(i);
}
}
vector<int>topo;
while(!Q.empty())
{
int node = Q.front();
topo.push_back(node);
Q.pop();
for(auto ch:adj[node])
{
indegree[ch]--;
if(indegree[ch]==0)
{
Q.push(ch);
}
}
}
return topo.size()!=V;
}
Using similar concept as used in color .
bool dfs(vector<int>adj[],int node,vector<int>&vis,vector<int>&dfs_vis)
{
vis[node] = 1;
dfs_vis[node] = 1;
bool check = 0;
for(auto ch:adj[node])
{
if(!vis[ch])
{
check |= dfs(adj,ch,vis,dfs_vis);
}
if(dfs_vis[ch]==1)
{
check = 1;
}
}
dfs_vis[node] = 0;
return check;
}
bool isCyclic(int V, vector<int> adj[]) {
vector<int>vis(V,0);
vector<int>dfs_vis(V,0);
bool check = 0;
for(int i=0;i<V;i++)
{
if(!vis[i])
{
check |= dfs(adj,i,vis,dfs_vis);
}
}
return check;
}
-
First create a parent array.
-
Then for every child of a node, make parent of child = node and when you encounter the visited node check if parent[node]! =child, then it is a cycle.
bool cycleCheck(vector<int>adj[],vector<int>&vis,vector<int>&parent,int node)
{
vis[node]=1;
bool check = 0;
for(auto ch:adj[node])
{
if(!vis[ch])
{
parent[ch]=node;
check |= cycleCheck(adj,vis,parent,ch);
}
else if(parent[node]!=ch)
{
check = 1;
}
}
return check;
}
int main()
{
vector<int>vis(V,0);
vector<int>parent(V,-1);
bool check = 0;
for(int i=0;i<V;i++)
{
if(!vis[i])
{
check |= cycleCheck(adj,vis,parent,i);
}
}
return check;
}
Uses same concept as dfs but traverse through bfs and queue is made of pair, <node,parent>
bool bfs(vector<int>edges[], vector<int> &vis, int idx) {
queue<pair<int, int>> Q;
Q.push({idx,-1});
while(!Q.empty())
{
pair<int,int> x = Q.front();
Q.pop();
vis[x.first]=1;
for(auto ch:edges[x.first])
{
if(vis[ch]==0)
{
vis[ch]=1;
Q.push({ch,x.first});
}
else if(x.second!=ch){
return 1;
}
}
}
return 0;
}
// Function to detect cycle in an undirected graph.
bool isCycle(int V, vector<int> adj[]) {
vector<int>vis(V,0);
vector<int>parent(V,-1);
queue<int>Q;
bool check = 0;
for(int i=0;i<V;i++)
{
if(!vis[i])
{
Q.push(i);
vis[i]=1;
while(!Q.empty())
{
int node = Q.front();
Q.pop();
for(auto ch:adj[node])
{
if(!vis[ch])
{
vis[ch] = 1;
parent[ch] = node;
Q.push(ch);
}
else
{
if(parent[node]!=ch)
{
check = 1;
}
}
}
}
}
}
return check;
}
1. Using simple DFS and Reversing any of its DFS vectors , But you need to be sure that Cycle is not present in the graph AND It also work if you not start from root.
void dfs(vector<int>adj[],vector<int>&vis,vector<int>&topo_sort,int node)
{
vis[node]=1;
for(auto ch:adj[node])
{
if(!vis[ch])
{
dfs(adj,vis,topo_sort,ch);
}
}
topo_sort.push_back(node);
}
vector<int> topoSort(int V, vector<int> adj[])
{
vector<int>topo_sort;
vector<int>vis(V,0);
for(int i=0;i<V;i++)
{
if(!vis[i])
{
dfs(adj,vis,topo_sort,0);
}
}
reverse(topo_sort.begin(),topo_sort.end());
return topo_sort;
}
vector<int> topoSort(int V, vector<int> adj[]) {
vector<int>indegree(V,0);
for(int i=0;i<V;i++)
{
for(auto ch:adj[i])
{
indegree[ch]++;
}
}
queue<int>Q;
for(int i=0;i<V;i++)
{
if(indegree[i]==0)
{
Q.push(i);
}
}
vector<int>topo;
while(!Q.empty())
{
int node = Q.front();
topo.push_back(node);
Q.pop();
for(auto ch:adj[node])
{
indegree[ch]--;
if(indegree[ch]==0)
{
Q.push(ch);
}
}
}
return topo;
}
DSU : Partitioning the individuals into different sets according to the groups in which they fall. This method is known as a Disjoint set Union which maintains a collection of Disjoint sets and each set is represented by one of its members call ultimate parent.
int findUpar(int node){
if(node == parent[node])
{
return node;
}
return parent[node] = findUpar(parent[node]);//path compression
}
Time Complexity: O(log n) on average per call because of path compression without it O(n).
It is used to merge two sets which is nothind but two trees and make them one tree we have to just make the parent of every node of one tree to the parent of the other tree , So there are two ways to decide which tree come under other or which tree become parent of other tree.
-
Here rank[i] is the height of the tree representing the set containing i. If the rank of left is less than the rank of right, then it’s best to move left under right, because that won’t change the rank of right (while moving right under left would increase the height). In the same way, if the rank of right is less than the rank of left, then we should move right under left. If the ranks are equal, it doesn’t matter which tree goes under the other, but the rank of the result will always be one greater than the rank of the trees.
void unionByRank(int u,int v){ int ulp_u = findUpar(u); int ulp_v = findUpar(v); if(ulp_u == ulp_v)return; if(Rank[ulp_u]<Rank[ulp_v]){ parent[ulp_u] = ulp_v; } else if(Rank[ulp_v]<Rank[ulp_u]){ parent[ulp_v] = ulp_u; } else{ parent[ulp_v] = ulp_u; Rank[ulp_u]++; } } Time Complexity: O(alpha(n)) on average per call because of path compression without it O(n).
-
If i is a representative of a set, size[i] is the number of the elements in the tree representing the set. If the size of left is less than the size of right, then it’s best to move left under right and increase size of right by size of left. In the same way, if the size of right is less than the size of left, then we should move right under left. and increase size of left by size of right. If the sizes are equal, it doesn’t matter which tree goes under the other.
void unionBySize(int u,int v){ int ulp_u = findUpar(u); int ulp_v = findUpar(v); if(ulp_u == ulp_v)return; if(Size[ulp_u]<Size[ulp_v]){ parent[ulp_u] = ulp_v; Size[ulp_v] += Size[ulp_u]; } else { parent[ulp_v] = ulp_u; Size[ulp_u] += Size[ulp_v]; } } Time complexity: O(log n) without Path Compression. Time complexity: O(alpha(n)) with Path Compression.
vector<int>Rank,parent;
vector<int>Size;
class DisjointSet{
public:
void print_rank(){
for(int i=1;i<Size.size();i++)
{
cout<<Size[i]<<" ";
}
cout<<endl;
}
DisjointSet(int n){
Rank.resize(n+1,0);
Size.resize(n+1,1);
parent.resize(n+1,0);
for(int i=0;i<=n;i++){
parent[i] = i;
}
}
int findUpar(int node){
if(node == parent[node])
{
return node;
}
return parent[node] = findUpar(parent[node]);//path compression
}
void unionByRank(int u,int v){
int ulp_u = findUpar(u);
int ulp_v = findUpar(v);
if(ulp_u == ulp_v)return;
if(Rank[ulp_u]<Rank[ulp_v]){
parent[ulp_u] = ulp_v;
}
else if(Rank[ulp_v]<Rank[ulp_u]){
parent[ulp_v] = ulp_u;
}
else{
parent[ulp_v] = ulp_u;
Rank[ulp_u]++;
}
}
void unionBySize(int u,int v){
int ulp_u = findUpar(u);
int ulp_v = findUpar(v);
if(ulp_u == ulp_v)return;
if(Size[ulp_u]<Size[ulp_v]){
parent[ulp_u] = ulp_v;
Size[ulp_v] += Size[ulp_u];
}
else {
parent[ulp_v] = ulp_u;
Size[ulp_u] += Size[ulp_v];
}
}
};
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// DSU data structure
// path compression + rank by union
class DSU {
int* parent;
int* rank;
public:
DSU(int n)
{
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = -1;
rank[i] = 1;
}
}
// Find function
int find(int i)
{
if (parent[i] == -1)
return i;
return parent[i] = find(parent[i]);
}
// Union function
void unite(int x, int y)
{
int s1 = find(x);
int s2 = find(y);
if (s1 != s2) {
if (rank[s1] < rank[s2]) {
parent[s1] = s2;
}
else if (rank[s1] > rank[s2]) {
parent[s2] = s1;
}
else {
parent[s2] = s1;
rank[s1] += 1;
}
}
}
};
class Graph {
vector<vector<int> > edgelist;
int V;
public:
Graph(int V) { this->V = V; }
// Function to add edge in a graph
void addEdge(int x, int y, int w)
{
edgelist.push_back({ w, x, y });
}
void kruskals_mst()
{
// Sort all edges
sort(edgelist.begin(), edgelist.end());
// Initialize the DSU
DSU s(V);
int ans = 0;
cout << "Following are the edges in the "
"constructed MST"
<< endl;
for (auto edge : edgelist) {
int w = edge[0];
int x = edge[1];
int y = edge[2];
// Take this edge in MST if it does
// not forms a cycle
if (s.find(x) != s.find(y)) {
s.unite(x, y);
ans += w;
cout << x << " -- " << y << " == " << w
<< endl;
}
}
cout << "Minimum Cost Spanning Tree: " << ans;
}
};
// Driver code
int main()
{
Graph g(4);
g.addEdge(0, 1, 10);
g.addEdge(1, 3, 15);
g.addEdge(2, 3, 4);
g.addEdge(2, 0, 6);
g.addEdge(0, 3, 5);
// Function call
g.kruskals_mst();
return 0;
}
-
Time Complexity: O(E _ logE) or O(E _ logV)
- Sorting of edges takes O(E * logE) time.
- After sorting, we iterate through all edges and apply the find-union algorithm. The find and union operations can take at most O(logV) time.
- So overall complexity is O(E _ logE + E _ logV) time. The value of E can be at most O(V2), so O(logV) and O(logE) are the same. Therefore, the overall time complexity is O(E * logE) or O(E*logV)
-
Auxiliary Space: O(V + E), where V is the number of vertices and E is the number of edges in the graph.
- Create a priority queue of pair<int,pair<int,int>> => {wt,{node,parent}} .
- Run simple BFS and circle can't be formed in MST because BFS is used and visited array is used
#include <bits/stdc++.h>
vector<pair<pair<int, int>, int>> calculatePrimsMST(int n, int m, vector<pair<pair<int, int>, int>> &g)
{
vector<pair<int,int>>graph[n+1];
for(int i=0;i<m;i++)
{
graph[g[i].first.first].push_back({g[i].first.second,g[i].second});
graph[g[i].first.second].push_back({g[i].first.first,g[i].second});
}
priority_queue<pair<pair<int,int>,int>, vector<pair<pair<int,int>,int>>, greater<pair<pair<int,int>,int>>> Q;
Q.push({{0,1},-1});
vector<pair<pair<int, int>, int>>ans;
vector<int>vis(n+1,0);
while(!Q.empty())
{
auto it = Q.top();
Q.pop();
int node = it.first.second;
int paren = it.second;
int wt = it.first.first;
if(vis[node]==1)continue;
if(paren!=-1)
{
ans.push_back({{node,paren},wt});
}
vis[node] = 1;
for(auto ch:graph[node])
{
int adjNode = ch.first;
if(vis[adjNode]==0)
{
Q.push({{ch.second,adjNode},node});
}
}
}
return ans;
}
A Bridge is an edge which upon removing increase the number of componenets in graph.
Steps to find bridges in GRAPH : (DFS used)
- Create 3 vectors (Discover, low, vis) And parent , timer variable.
- Discover : It stores the first time to reach any node , low : It stores the minimum time to reach node from any neighbour node and not parent of that node .
- initialize parent = -1 it is parent of starting node run dfs , in
void dfs(int node,int parent,int timer,vector<int>&dis,vector<int>&low,vector<vector<int>>&res,vector<int>graph[],vector<int>&vis)
{
vis[node] = 1;
dis[node]=low[node]=timer++;
for(auto ch:graph[node])
{
if(ch==parent)continue;
if(vis[ch]==0){
dfs(ch,node,timer,dis,low,res,graph,vis);
low[node] = min(low[ch],low[node]);
if(low[ch]>dis[node]){
res.push_back({ch,node});
}
}
else{
low[node] = min(low[node],low[ch]);
}
}
}
ALGO :
#include<bits/stdc++.h>
void dfs(int node,int parent,int timer,vector<int>&dis,vector<int>&low,vector<vector<int>>&res,vector<int>graph[],vector<int>&vis)
{
vis[node] = 1;
dis[node]=low[node]=timer++;
for(auto ch:graph[node])
{
if(ch==parent)continue;
if(vis[ch]==0){
dfs(ch,node,timer,dis,low,res,graph,vis);
low[node] = min(low[ch],low[node]);
if(low[ch]>dis[node]){
res.push_back({ch,node});
}
}
else{
low[node] = min(low[node],low[ch]);
}
}
}
vector<vector<int>> findBridges(vector<vector<int>> &edges, int v, int e) {
vector<int>graph[v];
for(int i=0;i<e;i++)
{
int u = edges[i][0];
int v = edges[i][1];
graph[u].push_back(v);
graph[v].push_back(u);
}
vector<int>vis(v,0);
vector<int>dis(v,0);
vector<int>low(v,0);
int parent = -1;
vector<vector<int>>result;
int timer = 0;
for(int i=0;i<v;i++)
{
if(!vis[i]){
dfs(i,parent,timer,dis,low,result,graph,vis);
}
}
return result;
}
Algorithm to find minimum distance of every node from source :(Dijkstra Algorithm, Bellman Ford Algorithm AND Toposort + Relaxation of nodes)
Used to find minimum distance of every node from source and can’t handle negative edges as well as negative cycle because it uses greedy approach i.e if minimum distance of node is found then it is not updated again.
Steps : (Still to write)
//Here adjacent list in the form of vector<vector<int>>adj[]
int MAX_INT = 1000000;
vector <int> dijkstra(int V, vector<vector<int>> adj[], int S)
{
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>>pq;
vector<int>dist(V,INT_MAX);
pq.push({0,S});
dist[S]=0;
while(!pq.empty())
{
auto temp = pq.top();
pq.pop();
auto node = temp.second;
auto cur_node_dist = temp.first;
if(dist[node]<cur_node_dist)continue;
for(auto ch:adj[node])
{
int child_dist = cur_node_dist + ch[1];
if(child_dist<dist[ch[0]])
{
dist[ch[0]] = child_dist;
pq.push({child_dist,ch[0]});
}
}
}
return dist;
}
O((V+E)*logv) ->
1 Extracting the minimum distance vertex also takes O(log V) time.
2 Each vertex is extracted once, and each edge is relaxed at most once.
3 Therefore, the total time for all extractions is O(V log V).
4 The total time for all edge relaxations is O(E log V).
Steps :
- Create a vector dist of size V and initialize it with INT_MAX and dist[source] = 0.
- Run a loop V-1 times and relax all the edges (i.e For each edges (u,v) with weight 'w' if dist[u] + wt < dist[v] then dist[v] = dist[u] + wt).
- Run a loop Vth time and if any edge is relaxed then it means negative cycle is present.
vector<int> bellmonFord(int n, int m, int src, vector<vector<int>> &edges) {
vector<int>dist(n+1,100000000);
dist[src] = 0;
for(int j=0;j<n;j++)
{
for(int i=0;i<m;i++)
{
int a = edges[i][0];
int b = edges[i][1];
int w = edges[i][2];
if( dist[a]!=100000000 && dist[a] +w<dist[b] )
{
dist[b] = dist[a] +w;
}
}
}
return dist;
}
Steps :
- Create a Toposort of the graph and stores it in an Vector.
- Initialize the distance of source node to 0 and all other nodes to INT_MAX.
- Run a loop of toposort and relax all the edges of the node , if dist[u] + wt < dist[v] then dist[v] = dist[u] + wt.
void dfs(vector<pair<int, int>>graph[],int node,vector<int>&vis,vector<int>&topo)
{
vis[node]=1;
for(auto ch: graph[node])
{
if(vis[ch.first]==0){
dfs(graph,ch.first,vis,topo);
}
}
topo.push_back(node);
}
vector<int> findMaxDistances(int n, int src, vector<vector<int>> &edges) {
vector<pair<int, int>> graph[n];
for (int i = 0; i < edges.size(); i++) {
int u = edges[i][0];
int v = edges[i][1];
int wt = edges[i][2];
graph[u].push_back({v, wt});
}
vector<int>topo;
vector<int>vis(n,0);
dfs(graph,src,vis,topo);
reverse(topo.begin(),topo.end());
vector<int> dist(n, 100000000);
dist[src] = 0;
for(int i=0;i<topo.size();i++)
{
int node = topo[i];
for(auto ch:graph[node]){
if(dist[ch.first]>dist[node]+ch.second){
dist[ch.first] = dist[node]+ch.second;
}
}
}
return dist;
}
Works well with graphs that have negative weight edges, as long as there are no negative weight cycles. Uses DP Time Complexity: O(V^3), where V is the number of vertices. This makes it less efficient for very large graphs but acceptable for dense graphs or graphs with a small number of vertices. Space Complexity: O(V^2) to store the distance matrix.
#include <bits/stdc++.h>
using namespace std;
void shortest_distance(vector<vector<int>> &matrix)
{
int n = matrix.size();
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (matrix[i][k] != -1 && matrix[k][j] != -1)
{
if (matrix[i][j] == -1 || matrix[i][k] + matrix[k][j] < matrix[i][j])
{
matrix[i][j] = matrix[i][k] + matrix[k][j];
}
}
}
}
}
}
Two Strongly Connected Component Connected in only one direction , if connected in both direction then whole graph become SCC
- Run DFS on the graph and store the order of nodes in a stack (stack conatains Toposort).
- Reverse the graph.
- Run DFS on the reversed graph and pop the nodes from the stack and No. of time you do dfs is the No. of SCC.
Logic : We don't do toposort of graph exactly , toposort is not possible because of presence of cycle in the graph , We do it to find the one element of scc before the other element of second scc because if you consider one scc as a single node then you can see that toposort is possible becuase interconnection between SCC's in one directional.
void dfs(int node,vector<int>&vis,vector<vector<int>>&graph,stack<int>&st)
{
vis[node] = 1;
for(auto ch: graph[node])
{
if(!vis[ch]){
dfs(ch,vis,graph,st);
}
}
st.push(node);
}
void Dfs(int node,vector<int>graph[],vector<int>&vis)
{
vis[node]=1;
for(auto ch:graph[node])
{
if(!vis[ch])
{
Dfs(ch,graph,vis);
}
}
}
int kosaraju(int V, vector<vector<int>>& adj)
{
vector<int>rev_graph[V];
for(int i=0;i<V;i++)
{
for(auto ch:adj[i])
{
rev_graph[ch].push_back(i);
}
}
stack<int>st;
vector<int>vis(V,0);
for(int i=0;i<V;i++)
{
if(!vis[i])
{
dfs(i,vis,adj,st);
}
}
vis.clear();
vis.resize(V,0);
int ans = 0;
while(!st.empty())
{
int node = st.top();
st.pop();
if(!vis[node])
{
ans++;
Dfs(node,rev_graph,vis);
}
}
return ans;
}
-
- Is it possible to color the graph with m colors.
- Minimum no. of colors required to color the graph.
-
-
problem statement : Given an undirected graph and an integer M. The task is to determine if the graph can be colored with at most M colors such that no two adjacent vertices of the graph are colored with the same color. Here coloring of a graph means the assignment of colors to all vertices. Print 1 if it is possible to colour vertices and 0 otherwise.
-
Logic :
- We will use backtracking to solve this problem.
- We will start from the first node and check if we can color it with any color.
- If we can color it with any color then we will move to the next node and if any eher further we are not able to color any node then we will backtrack and change the color of the previous node.
- We will keep on doing this until we reach the last node and if we are able to color all the nodes then we will return 1 else 0.
Time complexity : O(M^N) where N is the number of nodes and M is the number of colors , For both adjency matrix and adjency List Why ? Becuase Every node has M choices to color and we have N nodes. Space complexity : O(N) + O(N) because we are using a color array of size N and stack space of size N (recursion stack space).
Time Complexity Calculation : Total Number of nodes = (M^0 + M^1 + M^2 + M^3 + M^4 ....) = (M^N - 1)/(M-1) = O(M^N)
#include <bits/stdc++.h>
using namespace std;
bool check(int node, bool graph[101][101], int n, int c, vector<int> &color)
{
for (int i = 0; i < n; i++)
{
if (graph[i][node] || graph[node][i])
{
if (c == color[i])
return 0;
}
}
return 1;
}
bool dfs(int node, bool graph[101][101], int m, int n, vector<int> &color)
{
if (node == n)
{
return 1;
}
for (int i = 0; i < m; i++)
{
if (check(node, graph, n, i, color))
{
color[node] = i;
if (dfs(node + 1, graph, m, n, color))
{
return 1;
}
}
}
return 0;
}
bool graphColoring(bool graph[101][101], int m, int n)
{
vector<int> color(n, -1);
bool check = 1;
check = (1 && dfs(0, graph, m, n, color));
return check;
}
#include<bits/stdc++.h>
bool dfs(int node,vector<int>graph[],vector<int>&color,int c)
{
bool ans = 1;
for(auto ch:graph[node])
{
if(color[ch]==-1)
{
color[ch] = 1-c;
ans &= (dfs(ch,graph,color,1-c));
}
else if(color[ch]==c){
return 0;
}
}
return ans;
}
bool isGraphBirpatite(vector<vector<int>> &edges) {
int n = edges.size();
vector<int>graph[n];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(edges[i][j])
{
if(i==j)return 0; //Retrun False If self loop , because then it can't be BIPARTITE
graph[i].push_back(j);
graph[j].push_back(i);
}
}
}
vector<int>color(n,-1);
bool ans = 1;
for(int i=0;i<n;i++)
{
if(color[i]==-1)
{
color[0];
ans &=(dfs(i,graph,color,0));
}
}
return ans;
}
#include<bits/stdc++.h>
bool isGraphBirpatite(vector<vector<int>> &edges) {
int n = edges.size();
vector<int>graph[n];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(edges[i][j])
{
if(i==j)return 0; //Retrun False If self loop , because then it can't be BIPARTITE
graph[i].push_back(j);
graph[j].push_back(i);
}
}
}
vector<int>color(n,-1);
for(int i=0;i<n;i++)
{
if(color[i]==-1)
{
color[i] = 0;
queue<int>Q;
Q.push(i);
while(!Q.empty())
{
int node = Q.front();
Q.pop();
for(auto ch:graph[node])
{
if(color[ch]==-1)
{
color[ch] = 1-color[node];
Q.push(ch);
}
else{
if(color[ch]==color[node]){
return 0;
}
}
}
}
}
}
return 1;
}
-
-
-
-
Still to write
-
-
bool dfs(int node,vector<int>graph[],vector<int>&vis) { if(vis==vector<int>(vis.size(),1)){ return 1; } for(auto ch:graph[node]) { if(!vis[ch]){ vis[ch] = 1; if(dfs(ch,graph,vis)) { return 1; } vis[ch] = 0; } } return 0; } bool check(int N,int M,vector<vector<int>> Edges) { vector<int>graph[N+1]; for(int i=0;i<M;i++) { graph[Edges[i][0]].push_back(Edges[i][1]); graph[Edges[i][1]].push_back(Edges[i][0]); } bool ans = 0; for(int i=1;i<=N;i++) { vector<int>vis(N+1,0); vis[0]=1; vis[i]=1; ans |= dfs(i,graph,vis); vis[i]=0; } return ans; }
2. Hamiltonian Cycle : A cycle that visits every vertex exactly once and returns to the starting point.
Time Complexity : O(N!)
#include<bits/stdc++.h>
using namespace std;
struct Node{
Node\* links[26];
bool flag = false;
bool containKey(char ch)
{
return links[ch-'a']!=NULL;
}
void put(char ch,Node* node)
{
links[ch-'a'] = node;
}
Node* get(char ch)
{
return links[ch-'a'];
}
void setEnd()
{
flag = true;
}
bool isEnd()
{
return flag;
}
};
class Trie{
private:
Node _root;
public:
Trie(){
root = new Node();
}
void insert(string word){
Node_ node = root;
for(int i=0;i<word.size();i++)
{
if(!node->containKey(word[i]))
{
node->put(word[i],new Node());
}
node = node->get(word[i]);
}
node->setEnd();
}
bool search(string word){
Node*node = root;
for(int i=0;i<word.size();i++)
{
if(!node->containKey(word[i]))
{
return 0;
}
else{
node = node->get(word[i]);
}
}
return node->flag;
}
bool startsWith(string prefix){
Node *node = root;
for(int i=0;i<prefix.size();i++)
{
if(!node->containKey(prefix[i]))
{
return 0;
}
else{
node = node->get(prefix[i]);
}
}
return 1;
}
};
Trie(Max Xor Code) :
class Node{
public:
Node* links[2];
void put(int i,Node* node)
{
links[i] = node;
}
Node\* get(int i)
{
return links[i];
}
bool containKey(int i)
{
return links[i]!=NULL;
}
};
class Trie{
private:
Node* root = new Node();
public:
void insert(int num)
{
Node* node = root;
int temp = num;
for(int i=31;i>=0;i--)
{
int bit = (temp & (1<<i))?(1):0;
if(!node->containKey(bit))
{
node->put(bit,new Node());
}
node = node->get(bit);
}
}
int Xor(int num)
{
int ans = 0;
Node\* node = root;
int temp = num;
for(int i=31;i>=0;i--)
{
int bit = (temp & (1<<i))?(1):0;
int rev_bit = !bit;
if(node->containKey(rev_bit))
{
node = node->get(rev_bit);
ans += pow(2,i);
}
else
{
node = node->get(bit);
}
}
return ans;
}
int findMaximumXOR(vector<int>& nums) {
Trie trie;
int n = nums.size();
for(int i=0;i<n;i++)
{
trie.insert(nums[i]);
}
int maxi = 0;
for(int i=0;i<n;i++)
{
maxi = max(maxi,trie.Xor(nums[i]));
}
return maxi;
}
};
void merge(vector<int>&arr,int l1,int r1,int l2,int r2)
{
int n = r1-l1+1;
int m = r2-l2+1;
int a1[n],a2[m];
int j = 0;
for(int i=l1;i<=r1;i++)
{
a1[j] = arr[i];
j++;
}
j=0;
for(int i=l2;i<=r2;i++)
{
a2[j] = arr[i];
j++;
}
int k = l1;
int i=0;
j=0;
while(i<n && j<m)
{
if(a1[i]<=a2[j])
{
arr[k] = a1[i];
i++; k++;
}
else if(a1[i]>a2[j])
{
arr[k] = a2[j];
j++;
k++;
}
}
while(i<n){
arr[k] = a1[i];
k++;i++;
}
while(j<m){
arr[k] = a2[j];
k++; j++;
}
}
void mergeSort(vector<int>&arr,int left,int right)//arr,0,arr.size()
{
if(left<right)
{
int mid = (left + right)/2;
mergeSort(arr,left,mid);
mergeSort(arr,mid+1,right);
merge(arr,left,mid,mid+1,right);
}
}