I am trying to solve
http://www.spoj.com/problems/BOTTOM/
Here are the steps I am following:
1) Find the strongly connected components using Kosaraju's algorithm.
2) Consider a strongly connected component. Consider an edge u. Now consider all edges from u to some vertice v. If v lies in some other SCC, eliminate the whole strongly conected component. Else include all the elements in the solution.
However, I am constantly getting WA. Please help.
Here is my code:
struct Graph{
int V;
vector<int> *adj;
vector<int> *auxiliary;
vector<vector<int> > components;
Graph(int _V)
{
V=_V;
adj=new vector<int>[V+1];
auxiliary=new vector<int>[V+1];
}
void addEdge(int u, int v)
{
adj[u].push_back(v);
auxiliary[v].push_back(u);
}
void DFS(int u, bool *visited,stack<int> &nodes)
{
visited[u]=true;
int t;
stack<int> state;
bool present;
state.push(u);
while(!state.empty())
{
t=state.top();
visited[t]=true;
present=false;
for(vector<int>::iterator it=adj[t].begin();it!=adj[t].end();it++)
{
if(!visited[*it])
{
visited[*it]=true;
state.push(*it);
present=true;
}
}
if(!present)
{
nodes.push(state.top());
state.pop();
}
}
}
void DFSutil(int u,bool *visited,set<int> &members)
{
visited[u]=true;
stack<int> state;
int t;
bool present;
state.push(u);
while(!state.empty())
{
t=state.top();
present=false;
for(vector<int>::iterator it=auxiliary[t].begin();it!=auxiliary[t].end();it++)
{
if(!visited[*it])
{
visited[*it]=true;
present=true;
state.push(*it);
}
}
if(!present)
{
members.insert(state.top());
state.pop();
}
}
}
void kosaraju()
{
bool visited[V+1];
memset(visited,false,sizeof(visited));
stack<int> nodes;
int i,t;
//store the nodes, 1st DFS
for(i=1;i<=V;i++)
{
if(!visited[i])
DFS(i,visited,nodes);
}
//run DFS on the auxiliary(transposed) graph
set<int> members;
vector<int> answers;
memset(visited,false,sizeof(visited));
while(!nodes.empty())
{
t=nodes.top();
members.clear();
if(!visited[t])
{
DFSutil(t,visited,members);
set<int>::iterator it;
for(it=members.begin();it!=members.end();it++)
{
vector<int>::iterator itt;
for(itt=adj[*it].begin();itt!=adj[*it].end();itt++)
{
if(!present(members,*itt))
break;
}
if(itt!=adj[*it].end())
break;
}
if(it==members.end())
{
for(it=members.begin();it!=members.end();it++)
answers.pb(*it);
}
}
nodes.pop();
}
sort(answers.begin(),answers.end());
tr(answers,itt)
printf("%d ",*itt);
printf("\n");
}
};
At first glance, it looks like your depth-first search (assuming DFS is supposed to be depth-first) might not actually be depth-first, but rather a breadth-first-search, since it adds all of the unvisited neighbors to the search queue immediately. I think you might need to add a break statement:
for(vector<int>::iterator it=adj[t].begin();it!=adj[t].end();it++)
{
if(!visited[*it])
{
visited[*it]=true;
state.push(*it);
present=true;
-----------> break;
}
}
In comments, sudeepdino008 correctly pointed out that DFS can be implemented with a stack, but in this case I believe that vertices shouldn't be marked as visited until they are removed from the stack:
for(vector<int>::iterator it=adj[t].begin();it!=adj[t].end();it++)
{
if(!visited[*it])
{
----------> //visited[*it]=true;
state.push(*it);
present=true;
}
}
Here's the problem: Consider a simple graph
1->2
1->3
3->2
With the original algorithm, vertices will be added to nodes in the order (3,2,1) rather than (2,3,1). This means that, in the second part of the algorithm, when the backwards BFS is performed, 2 will be selected before 3, and the algorithm will incorrectly output that (2,3) is a strongly connected component.
Related
When I try to implement a topological sort in C++ with an unordered_map<string, vector<string>> which represents the graph, I encounter an unexplainable error (from my part). Specifically, this happens only when the 'current node' that is being visited does not exist as a key in the unordered_map (i.e, it has no outgoing edges). Instead of returning the 'correct' order, it terminates the function call topSort entirely and returns only a small subset of the order.
The code returns: ML, AML, DL
Instead, a possible correct solution could be: LA, MT, MA, PT, ML, AML, DL
Can anyone explain why this happens?
The following is a small code snippet where the problem occurs:
// 0 -> white (node has not been visited)
// 1 -> grey (node is currently being visited)
// 2 -> black (node is completely explored)
bool topSortVisit(unordered_map<string, vector<string>>& graph,
unordered_map<string, int>& visited, string node, vector<string>& result){
if(visited[node] == 1) return false;
if(visited[node] == 2) return true;
// Mark current node as being visited.
visited[node] = 1;
// node might not have outgoing edges and therefore not in the
// unordered_map (graph) as a key.
for(auto neighbor : graph[node]){
if(!topSortVisit(graph, visited, neighbor, result)) return false;
}
result.push_back(node);
visited[node] = 2;
return true;
}
vector<string> topSort(unordered_map<string, vector<string>>& graph){
unordered_map<string, int> visited;
vector<string> result;
// Should visit all nodes with outgoing edges in the graph.
for(auto elem : graph){
string node = elem.first;
bool acyclic = topSortVisit(graph, visited, node, result);
if(!acyclic){
cout << "cycle detected\n";
return vector<string>{};
}
}
reverse(result.begin(), result.end());
return result;
}
And here is the code to reproduce everything:
#include<iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
using namespace std;
bool topSortVisit(unordered_map<string, vector<string>>& graph,
unordered_map<string, int>& visited, string node, vector<string>& result){
if(visited[node] == 1) return false;
if(visited[node] == 2) return true;
visited[node] = 1;
for(auto neighbor : graph[node]){
if(!topSortVisit(graph, visited, neighbor, result)) return false;
}
result.push_back(node);
visited[node] = 2;
return true;
}
vector<string> topSort(unordered_map<string, vector<string>>& graph){
unordered_map<string, int> visited;
vector<string> result;
for(auto elem : graph){
string node = elem.first;
bool acyclic = topSortVisit(graph, visited, node, result);
if(!acyclic){
cout << "cycle detected\n";
return vector<string>{};
}
}
return result;
}
unordered_map<string, vector<string>> makeGraph(vector<pair<string, string>> courses){
unordered_map<string, vector<string>> graph;
for(auto p : courses){
graph[p.first].push_back(p.second);
}
return graph;
}
int main(){
vector<pair<string, string>> pairs;
pairs.push_back(make_pair("LA", "ML"));
pairs.push_back(make_pair("MT", "ML"));
pairs.push_back(make_pair("MA", "PT"));
pairs.push_back(make_pair("PT", "ML"));
pairs.push_back(make_pair("ML", "DL"));
pairs.push_back(make_pair("ML", "AML"));
auto graph = makeGraph(pairs);
vector<string> result = topSort(graph); // ML, AML, DL
// A possible correct solution could be: LA, MT, MA, PT, ML, AML, DL
for(string s : result){
cout << s << " ";
}
cout << "\n";
}
Inserting into an unordered_map invalidates iterators into the map if it rehashes. That breaks your loop with auto elem : graph (which, incidentally, copies your vector<string> objects; use auto &elem instead). Pass your graph as const& to avoid such shenanigans; the compiler will then gently suggest that you use at instead of operator[].
I was looking into BFS search code provide in here:
// Program to print BFS traversal from a given
// source vertex. BFS(int s) traverses vertices
// reachable from s.
#include<iostream>
#include <list>
using namespace std;
// This class represents a directed graph using
// adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing adjacency
// lists
list<int> *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// prints BFS traversal from a given source s
void BFS(int s);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
queue.pop_front();
// Get all adjacent vertices of the dequeued
// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Breadth First Traversal "
<< "(starting from vertex 2) \n";
g.BFS(2);
return 0;
}
In the constructor of Graph class they created a adjacency list in the heap but they never use a delete to free the memory. My question is as following
a) Is there any chance of memory leak?
If there is any memory leak how could we solve the problem?
Yes there are leaks.
Leak 1 is new list<int>[V];
Leak 2 is new bool[V];
Looks like some guy with Java or C# background wrote this piece of code. To fix the leaks use delete[] in the function void Graph::BFS(int s) also use a destructor to delete the list.
Then, you might consider std::shared_ptr.
Is there any chance of memory leak?
Yes, there is a high chance for a memory leak.
If there is any memory leak how could we solve the problem?
Generally, this can be solved by implementing a destructor. Then again, according to the rule of three, we would need a copy-constructor as well, just in case an end user decides to copy one list to another.
But we could actually sidestep this by not dynamically-allocating in the first place! Let's reimplement with std::vector:
class Graph
{
int V;
vector<list<int>> adj;
public:
Graph(int V);
// ...
};
Graph::Graph(int V)
{
this->V = V;
adj.assign(V, list<int>()); // std::vector::assign
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
vector<bool> visited(V); // see note below *
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
queue.pop_front();
// Get all adjacent vertices of the dequeued
// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
There are a ton of other minor issues with this code, but I shall leave that as an exercise for the reader.
*Note: vector<bool> isn't your normal vector.
I am trying to modify the DFS algorithm in C++ from the geeks4geeks site so that the graph is created according to users input.
Original code:
// C++ program to print DFS traversal from
// a given vertex in a given graph
#include<iostream>
#include<list>
using namespace std;
// Graph class represents a directed graph
// using adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing
// adjacency lists
list<int> *adj;
// A recursive function used by DFS
void DFSUtil(int v, bool visited[]);
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// DFS traversal of the vertices
// reachable from v
void DFS(int v);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and
// print it
visited[v] = true;
cout << v << " ";
// Recur for all the vertices adjacent
// to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// DFS traversal of the vertices reachable from v.
// It uses recursive DFSUtil()
void Graph::DFS(int v)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function
// to print DFS traversal
DFSUtil(v, visited);
}
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Depth First Traversal"
" (starting from vertex 2) \n";
g.DFS(2);
return 0;
}
I've changed the main() function to read from cin as follows, leaving the remaining part of the code the same:
int main()
{
int V,A[4][2];
cin>>V;
Graph g(V);
for(int i=0;i<V;i++){
cin>> A[i][0];
cin>>A[i][1];
}
for (int j=0;j<V;j++){
g.addEdge(A[j][0], A[j][1]);
}
g.DFS(2);
return 0;
}
The graph is given in adjacency list, for example with the following input data (first line is the V parameter, remaining lines represent edges from one node to another):
4
1 2
2 3
3 1
4 2
4 1
These are stored in the array sequentially, so once the data is read, I expect that:
A[0][0]=1, A[0][1]=2 (edge 1->2)
A[1][0]=2, A[1][1]=3 (edge 2->3)
...
But the output of the IDE is:
Command terminated by signal 11.
I think this is a segmentation fault and it means that I am trying to access memory I should not but I don't know how to fix this. Any ideas?
The problem with your reading function is that you can read only one edge per node. So a part of the edges is ignored. Consider this refactoring:
int main()
{
int V,A[2];
cin>>V;
Graph g(V);
while ( cin>> A[0]>>A[1] ) {
if (A[0]<0 || A[1]<0 || A[0]>=V || A[1]>=V)
cout << A[0]<<"->"<<A[1]<<" refers to a non-existent node"<<endl;
else g.addEdge(A[0], A[1]);
}
g.DFS(2);
return 0;
}
As you see, I've added a validation on the data read in order to avoid obvious errors. Running it on your test data will show you that there's a problem with your node identifications: you go from 1 to 4 in the test data, while your code expects from 0 to 3 (because the graph is implemented as an array of V adjacency lists and you shall not go out of range).
Here an online demo.
So, I implemented the DFS in an iterative manner by the following method:
void dfsiter (graph * mygraph, int foo, bool arr[])
{
stack <int> mystack;
mystack.push(foo);
while (mystack.empty() == false)
{
int k = mystack.top();
mystack.pop();
if (arr[k] == false)
{
cout<<k<<"\t";
arr[k] = true;
auto it = mygraph->edges[k].begin();
while (it != mygraph->edges[k].end())
{
if (arr[*it] == false)
{
mystack.push(*it);
}
it++;
}
}
}
}
The above code works completely fine. Now, I want to detect cycles in an undirected graph using the above code (Iterative DFS). Now, I read that, If an unexplored edge leads to a node visited before, then the graph contains a cycle. Therefore, I just want to ask you, how do I exactly keep track of all this?
I have taken my graph to be like this:
class graph
{
public:
int vertices;
vector < vector<int> > edges;
};
Should I change the above to:
class graph
{
public:
int vertices;
vector < vector<pair<int,bool> > edges;
};
Where the bool for each edge will be marked true? And what changes will I need to do in the above code for DFS for detecting the cycle? I tried but I couldn't really think of a way of doing it. Thanks!
You can store a "father" node f in DFS tree for each vertex v, i.e. the vertex from which DFS came to the vertex v. It can be stored in the stack for example. In this case you store pairs in stack, first value is the vertex v and the second one is its father f.
An undirected graph has a cycle if and only if you meet an edge vw going to already visited vertex w, which is not the father of v.
You can see the modified and cleaned code below.
bool hascycle (graph * mygraph, int start, bool visited[])
{
stack <pair<int, int> > mystack;
mystack.push(make_pair(start, -1));
visited[start] = true;
while (!mystack.empty())
{
int v = mystack.top().first;
int f = mystack.top().second;
mystack.pop();
const auto &edges = mygraph->edges[v];
for (auto it = edges.begin(); it != edges.end(); it++)
{
int w = *it;
if (!visited[w])
{
mystack.push(make_pair(w, v));
visited[w] = true;
}
else if (w != f)
return true;
}
}
return false;
}
Note: if the graph is disconnected, then you must start DFS from several vertices, ensuring that the whole graph is visited. It can be done in O(V + E) total time.
I need to sort a vector<vector<int> > vecOfVectors; lexicographically.
So, my vecOfVectors before sorting lexicographically is:
((0,100,17,2),(2,3,1,3),(9,92,81,8),(0,92,92,91),(10,83,7,2),(1,2,3,3))
In order to do so I am using the following function:
std::sort(vecOfVectors.begin(),vecOfVectors.end(),lexicographical_compare);
So, my vecOfVectors after sorting lexicographically is now:
((0,92,92,91),(0,100,17,2),(1,2,3,3),(2,3,1,3),(9,92,81,8),(10,83,7,2))
Now given a vector I need to search its position in this sorted vecOfVectors -- somthing like binary search will work great. Is there some build in function in c++ stl that I can use to perform the binary search?
For example:
the position of (0,92,92,91) is 0; position of (0,100,17,2) is 1; position of (1,2,3,3) is 2; position of (2,3,1,3) is 3; position of (9,92,81,8) is 4; position of (10,83,7,2) is 5.
There's no need to add lexicographical_compare, that's already how vectors are compared.
Depending on your exact use case you're looking for std::lower_bound or std::upper_bound, std::binary_search or std::equal_range- all of these operate on sorted vectors.
A complete example with your data and c++11 is below. It constructs your vector, sorts it (showing the order you mention), then finds a single value in the vector.
#include <vector>
#include <iostream>
#include <algorithm>
void print(const std::vector<int> & v) {
std::cout<<"(";
for(auto x=v.begin(); x!=v.end(); ++x) {
std::cout<<*x<<",";
}
std::cout<<")";
}
void print(const std::vector<std::vector<int>> & v) {
std::cout<<"(";
for(auto x=v.begin(); x!=v.end(); ++x) {
print(*x);
std::cout<<",";
}
std::cout<<")"<<std::endl;
}
int main() {
std::vector<std::vector<int>> v {
{0,100,17,2},
{2,3,1,3},
{9,92,81,8},
{0,92,92,91},
{0,92,92,91},
{10,83,7,2},
{1,2,3,3}
};
print(v);
std::sort(v.begin(), v.end());
print(v);
std::vector<int> key = { 0,100, 17, 2 };
auto it = std::lower_bound(v.begin(), v.end(), key);
if(it!=v.end() && key==*it) {
std::cout<<"Found it"<<std::endl;
} else {
std::cout<<"Not found"<<std::endl;
}
}
As I said in comments create a function:
bool compare(vector<int> A,vector<int> B)
{
int i=0;
while(i<(A.size()<B.size())?A.size():B.size())
{
if(A[i]<B[i])
{
return 1;
}
else if(A[i]==B[i])
{
i++;
}
else
{
return 0;
}
}
return 0;
}