diff --git a/Graph/reviseGraph.cpp b/Graph/reviseGraph.cpp new file mode 100644 index 00000000..3b3ad9cd --- /dev/null +++ b/Graph/reviseGraph.cpp @@ -0,0 +1,63 @@ +#include +using namespace std; +void dfs(int source,vector adj[],vector& visited){ + cout << source << " "; + visited[source] = true; + for(auto it = adj[source].begin();it != adj[source].end();it++){ + if(!visited[*it]){ + dfs(*it,adj,visited); + } + } +} +void bfs(int source,vector adj[],vector& visited){ + queue q; + q.push(source); + while(!q.empty()){ + int temp = q.front(); + cout << temp << " "; + q.pop(); + for(auto it = adj[temp].begin();it != adj[temp].end(); it++){ + if(!visited[*it]){ + visited[*it] = true; + q.push(*it); + } + } + } +} + +int main(){ + int v,e; + cin >> v >> e; + // 1-based indexing + vector adj[v + 1]; + for(int i = 0;i < e;i++){ + // Undirected graph + int a,b; + cin >> a >> b; + adj[a].push_back(b); + adj[b].push_back(a); + } + // for(int i = 0;i < v + 1;i++){ + // cout << i << " - "; + // for(auto it = adj[i].begin();it != adj[i].end();it++){ + // cout << *it << " "; + // } + // cout << "\n"; + // } + vector visited(v + 1,false); + int source = 1; + // dfs(source,adj,visited); + // bfs(source,adj,visited); + + // Number of Components + // The number of times dfs is called the number of components + int count = 0; + for(int i = 1;i <= v;i++){ + if(!visited[1]) { + dfs(i,adj,visited); + count++; + }; + } + cout << endl << count << endl; + return 0; +} \ No newline at end of file diff --git a/Graph/reviseGraph1.cpp b/Graph/reviseGraph1.cpp new file mode 100644 index 00000000..0021f56e --- /dev/null +++ b/Graph/reviseGraph1.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +using namespace std; +class Solution{ +public: + bool detectCycleBfs(vector adj[],int src,vector&vis){ + queue> q; + q.push({src,-1}); + vis[src] = true; + while(!q.empty()){ + int dest = q.front().first; + int par = q.front().second; + q.pop(); + for(auto i : adj[dest]){ + if(!vis[i]){ + vis[i] = true; + q.push({i,dest}); + } + else{ + if(par != i) return true; + } + } + } + return false; + } + bool detectCycleDfs(vectoradj[],int src,int par,vector&vis){ + vis[src] = true; + for(auto i : adj[src]){ + if(!vis[i]){ + if(detectCycleDfs(adj,i,src,vis)) return true; + } + else if(par != i) return true; + } + return false; + } + bool isCycle(vector adj[],int v){ + vector vis(v + 1,false); + for(int i = 0;i <= v;i++){ + if(!vis[i] && detectCycleBfs(adj,i,vis)) return true; + } + return false; + } +}; + + +int main(){ + int v,e; + cin >> v >> e; + vector adj[v + 1]; + for(int i = 0;i < e;i++){ + int a,b; + cin >> a >> b; + adj[a].push_back(b); + adj[b].push_back(a); + } + Solution s; + cout << (s.isCycle(adj,v) ? "true" : "false"); + return 0; +} + diff --git a/Graph/reviseGraph2.cpp b/Graph/reviseGraph2.cpp new file mode 100644 index 00000000..4fbe8c45 --- /dev/null +++ b/Graph/reviseGraph2.cpp @@ -0,0 +1,46 @@ +#include +#include +using namespace std; +int dfs(int n,int src,vector adj[],vector&vis,vector&ans){ + vis[src] = true; + for(auto i : adj[src]){ + if(!vis[i]) n = dfs(n,i,adj,vis,ans); + } + ans[n] = src; + return n-1; +} +void topsort(int v,vector adj[],vector &vis){ + vector ans(v); + int n = v - 1; + // Unoptimized version + // for(int i = 1;i <= v;i++){ + // if(!vis[i]){ + // vector visited; + // dfs(i,adj,vis,visited); + // for(auto visi : visited){ + // ans[n] = visi; + // n--; + // } + // } + // } + // Optimized Version + for(int i = 1;i <= v;i++){ + if(!vis[i]){ + n = dfs(n,i,adj,vis,ans); + } + } + for(auto i : ans) cout << i << " "; +} +int main(){ + int v,e; + cin >> v >> e; + vector adj[v + 1]; + vector vis(v + 1,false); + for(int i = 0;i < e;i++){ + int a,b; + cin >> a >> b; + adj[a].push_back(b); + } + topsort(v,adj,vis); + return 0; +} \ No newline at end of file diff --git a/Graph/reviseGraph3.cpp b/Graph/reviseGraph3.cpp new file mode 100644 index 00000000..2cb6f022 --- /dev/null +++ b/Graph/reviseGraph3.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +using namespace std; +// Kahn's Algorithm for Topological Ordering + +void topsort(int v,vector adj[],vector &vis){ + vector inDegree(v + 1,0); + for(int i = 0;i < v; i++){ + for(auto j : adj[i]){ + inDegree[j]++; + } + } + queue nodes; + for(int i = 0;i < v;i++){ + if(inDegree[i] == 0) nodes.push(i); + } + vector ans(v); + int i = 0; + while(!nodes.empty()){ + int temp = nodes.front();nodes.pop(); + ans[i++] = temp; + for(auto node : adj[temp]){ + inDegree[node]--; + if(inDegree[node] == 0) nodes.push(node); + } + } + if(i != v){ + cout << "Cycle Found\n"; + return; + } + for(auto i : ans) cout << i << " "; +} +int main(){ + int v,e; + cin >> v >> e; + vector adj[v]; + vector vis(v,false); + for(int i = 0;i < e;i++){ + int a,b; + cin >> a >> b; + adj[a].push_back(b); + } + topsort(v,adj,vis); + return 0; +} \ No newline at end of file diff --git a/Graph/reviseGraph4.cpp b/Graph/reviseGraph4.cpp new file mode 100644 index 00000000..e0cacba9 --- /dev/null +++ b/Graph/reviseGraph4.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include +using namespace std; +// Kahn's Algorithm for Topological Ordering + +vector topsort(int v,vector> adj[],vector &vis){ + vector inDegree(v,0); + for(int i = 0;i < v; i++){ + for(auto j : adj[i]){ + inDegree[j.first]++; + } + } + queue nodes; + for(int i = 0;i < v;i++){ + if(inDegree[i] == 0) nodes.push(i); + } + vector ans(v); + int i = 0; + while(!nodes.empty()){ + int temp = nodes.front();nodes.pop(); + ans[i++] = temp; + for(auto node : adj[temp]){ + inDegree[node.first]--; + if(inDegree[node.first] == 0) nodes.push(node.first); + } + } + return ans; +} + +// Shortest/Longest Path on a DAG +// for longest path we just need to multiply all the edge values with +// negative one and then find the minimum distanve that way +// and return the ans after multiplying with negative one + +void sssp_dag(int src,int v,vector> adj[],vector&ts,vector &dist){ + dist[src] = 0; + for(int i = 0;i < v;i++){ + int currNode = ts[i]; + int d = dist[currNode]; + for(auto node : adj[currNode]){ + dist[node.first] = min(dist[node.first],d + node.second); + } + } +} +int main(){ + int v,e; + cin >> v >> e; + vector> adj[v]; + vector vis(v,false); + for(int i = 0;i < e;i++){ + int a,b,w; + cin >> a >> b >> w; + adj[a].push_back({ b, w }); + } + auto ans = topsort(v,adj,vis); + vector dist(v,INT_MAX); + for(auto i : ans) cout << char('A' + i) << " "; + sssp_dag(0,v,adj,ans,dist); + cout << "\n"; + for(auto i : ans) cout << dist[i] << " "; + return 0; +} \ No newline at end of file diff --git a/Graph/reviseGraph5.cpp b/Graph/reviseGraph5.cpp new file mode 100644 index 00000000..0d62e153 --- /dev/null +++ b/Graph/reviseGraph5.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +#include +using namespace std; +// Kahn's Algorithm for Topological Ordering +class Edge{ +public: + int from; + int to; + int cost; +}; +vector topsort(int v,vector> adj[],vector &vis){ + vector inDegree(v,0); + for(int i = 0;i < v; i++){ + for(auto j : adj[i]){ + inDegree[j.first]++; + } + } + queue nodes; + for(int i = 0;i < v;i++){ + if(inDegree[i] == 0) nodes.push(i); + } + vector ans(v); + int i = 0; + while(!nodes.empty()){ + int temp = nodes.front();nodes.pop(); + ans[i++] = temp; + for(auto node : adj[temp]){ + inDegree[node.first]--; + if(inDegree[node.first] == 0) nodes.push(node.first); + } + } + return ans; +} + +void sssp_dag(int src,int v,vector> adj[],vector&ts,vector &dist){ + dist[src] = 0; + for(int i = 0;i < v;i++){ + int currNode = ts[i]; + int d = dist[currNode]; + for(auto node : adj[currNode]){ + dist[node.first] = min(dist[node.first],d + node.second); + } + } +} + +// Adjacency List Implementation +vector bellmanFord(int v,vector> adj[],int src){ + vector dist(v,INT_MAX); + dist[src] = 0; + for(int i = 0;i < v;i++){ + for(auto edge : adj[i]){ + if(dist[i] + edge.second < dist[edge.first]){ + dist[edge.first] = dist[i] + edge.second; + } + } + } + for(int i = 0;i < v;i++){ + for(auto edge : adj[i]){ + if(dist[i] + edge.second < dist[edge.first]){ + dist[i] = INT_MIN; + dist[edge.first] = INT_MIN; + } + } + } + return dist; +} + +// Edge list Implementation +vector bellmanFord(int v,vector&edges,int src){ + vector dist(v,INT_MAX); + dist[src] = 0; + for(int i = 0;i < v - 1;i++){ + for(Edge edge : edges){ + if(dist[edge.from] + edge.cost < dist[edge.to]){ + dist[edge.to] = dist[edge.from] + edge.cost; + } + } + } + for(int i = 0;i < v - 1;i++){ + for(Edge edge : edges){ + if(dist[edge.from] + edge.cost < dist[edge.to]){ + // We need to set edge.from dist + // -inf as well + dist[edge.from] = INT_MIN; + dist[edge.to] = INT_MIN; + } + } + } + return dist; +} +int main(){ + int v,e; + cin >> v >> e; + +// Adjacency list implementation + vector> adj[v]; + vector vis(v,false); + for(int i = 0;i < e;i++){ + int a,b,w; + cin >> a >> b >> w; + adj[a].push_back({ b, w }); + } + +// Edge List Implementation + vector edges(e); + for(int i = 0;i < e;i++){ + cin >> edges[i].from >> edges[i].to >> edges[i].cost; + } + vector dist(v,INT_MAX); + auto ans = bellmanFord(v,adj,0); + for(int i = 0;i < v;i++){ + int val = ans[i]; + cout << i << " -> "; + if(val == INT_MIN) cout << "N\n"; + else cout << val << "\n"; + } + // for(auto i : ans){ + // if(i == INT_MIN) cout << "N "; + // else cout << i << " "; + // } + return 0; +} \ No newline at end of file diff --git a/Graph/reviseGraph6.cpp b/Graph/reviseGraph6.cpp new file mode 100644 index 00000000..cc036b78 --- /dev/null +++ b/Graph/reviseGraph6.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#define inf std::numeric_limits::infinity() +#define ninf -1*inf +using namespace std; + +vector> createGraph(int n,int e){ + vector> graph(n,vector(n,inf)); + for(int i = 0;i < n;i++){ + int a,b,c; + cin >> a >> b >> c; + graph[a][b] = c; + graph[i][i] = 0; + } + return graph; +} + +class FloydWarshallSolver{ + int n; + bool solved; + vector> dp; + vector> next; + #define REACHES_NEGATIVE_CYCLE -1 + +public: + FloydWarshallSolver(vector>&graph){ + n = graph.size(); + solved = false; + dp.resize(n,vector(n)); + next.resize(n,vector(n)); + for(int i = 0;i < n;i++){ + for(int j = 0;j < n;j++){ + if(graph[i][j] != inf) next[i][j] = j; + dp[i][j] = graph[i][j]; + } + } + } + vector> getAPSPMatrix(){ + if(!solved) solve(); + return dp; + } + void solve(){ + for(int k = 0;k < n;k++){ + for(int i = 0;i < n;i++){ + for(int j = 0;j < n;j++){ + if(dp[i][k] + dp[k][j] < dp[i][j]){ + dp[i][j] = dp[i][k] + dp[k][j]; + next[i][j] = next[i][k]; + } + } + } + } + // For propogating the negative cycle + for(int k = 0;k < n;k++){ + for(int i = 0;i < n;i++){ + for(int j = 0;j < n;j++){ + if(dp[i][k] + dp[k][j] < dp[i][j]){ + dp[i][j] = ninf; + next[i][j] = REACHES_NEGATIVE_CYCLE; + } + } + } + } + solved = true; + } + + vector constructShortestPath(int start,int end){ + vector path; + if(dp[start][end] == inf) return path; + int curr = start; + for(;curr != end;curr = next[curr][end]){ + if(curr == REACHES_NEGATIVE_CYCLE) vector(1,-1); + path.push_back(curr); + } + if(next[curr][end] == REACHES_NEGATIVE_CYCLE) vector(1,-1); + path.push_back(end); + return path; + } +}; + +int main(){ + int n,e; + cin >> n >> e; + vector> graph = createGraph(n,e); + FloydWarshallSolver* solver = new FloydWarshallSolver(graph); + auto dist = solver->getAPSPMatrix(); + for(int i = 0;i < n;i++){ + for(int j = 0;j < n;j++){ + printf("Shortest Path from %d to %d is %.2f\n",i,j,dist[i][j]); + } + } + cout << endl; + for(int i = 0;i < n;i++){ + for(int j = 0;j < n;j++){ + vector path = solver->constructShortestPath(i,j); + string str = ""; + if(path.size() == 1 && path[0] == -1){ + str = "has an infinite number of solution! (negative cycle case)"; + } + else if(path.size() == 0){ + str = "does not exist, node "+to_string(i)+" doesn't reach node "+to_string(j); + } + else{ + int k; + for(k = 0;k < path.size() - 1;k++){ + str += to_string(path[k]); + str += " "; + // str += "->"; + } + string end = ""; + if(k < path.size()) end = to_string(path[k]); + str = "[" + str + end + "]"; + } + cout << "The shortest path from node " << i << " to node " << j << " " << str << "\n"; + } + } + return 0; +} \ No newline at end of file