This is a working Prim's algorithm taking in three ints. My issue is that my edges are letters, and not numbers. I can't seem to debug it to make it work with char, instead of int, so I am turning to you guys. Any help would be appreciated!
using namespace std;
# define INF 0x3f3f3f3f
// iPair ==> Integer Pair
typedef pair<int, int> iPair;
// This class represents a directed graph using
// adjacency list representation
class Graph
{
int V; // No. of vertices
// In a weighted graph, we need to store vertex
// and weight pair for every edge
list< pair<int, int> > *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int u, int v, int w);
// Print MST using Prim's algorithm
void primMST();
};
// Allocates memory for adjacency list
Graph::Graph(int V)
{
this->V = V;
adj = new list<iPair> [V];
}
void Graph::addEdge(int u, int v, int w)
{
adj[u].push_back(make_pair(v, w));
adj[v].push_back(make_pair(u, w));
}
// Prints shortest paths from src to all other vertices
void Graph::primMST()
{
// Create a priority queue to store vertices that
// are being preinMST. This is weird syntax in C++.
// Refer below link for details of this syntax
// http://geeksquiz.com/implement-min-heap-using-stl/
priority_queue< iPair, vector <iPair> , greater<iPair> > pq;
int src = 0; // Taking vertex 0 as source
// Create a vector for keys and initialize all
// keys as infinite (INF)
vector<int> key(V, INF);
// To store parent array which in turn store MST
vector<int> parent(V, -1);
// To keep track of vertices included in MST
vector<bool> inMST(V, false);
// Insert source itself in priority queue and initialize
// its key as 0.
pq.push(make_pair(0, src));
key[src] = 0;
/* Looping till priority queue becomes empty */
while (!pq.empty())
{
// The first vertex in pair is the minimum key
// vertex, extract it from priority queue.
// vertex label is stored in second of pair (it
// has to be done this way to keep the vertices
// sorted key (key must be first item
// in pair)
int u = pq.top().second;
pq.pop();
inMST[u] = true; // Include vertex in MST
// 'i' is used to get all adjacent vertices of a vertex
list< pair<int, int> >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
// Get vertex label and weight of current adjacent
// of u.
int v = (*i).first;
int weight = (*i).second;
// If v is not in MST and weight of (u,v) is smaller
// than current key of v
if (inMST[v] == false && key[v] > weight)
{
// Updating key of v
key[v] = weight;
pq.push(make_pair(key[v], v));
parent[v] = u;
}
}
}
// Print edges of MST using parent array
for (int i = 1; i < V; ++i)
printf("%d - %d\n", parent[i], i);
}
I tried changing the typedef pair to <char, char>, and the *adj to <char, char>. The problem arrives in the function addEdge, using the list to create my graph.
Your code seems to be taken from here.
When you run the code online there everything works fine.
You can diff your version with the theirs see what went wrong.
Related
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 have a set of edges E, and I want to know if I can safely remove edge i in E, meaning if I remove it from the graph, the graph should still be connected.
In my understanding that implies that edge i, has to lie on a circle.
The output should be a list of indices of all edges I can't remove.
The problem:
My different solutions seem to do the right thing, but are far too slow (inefficient).
One of my solutions was:
1. Loop through all edges i in E
2. Loop through all edges x in V
3. Add edge x to the graph (excluding edge i) until nodes of i are connected or end reached
4. If no connection possible, edge is not removable and added to the list
This way was way too slow.
I then decided to rewrite my code and use breadth-first-search to look if another path is possible without edge i.
I thought it would be performant enough, but it seems it's not. Either I have implemented in a very bad way or that's also the wrong algorithm for this task.
Here is the algorithm in the C++ code I have (removed some not important parts):
struct connection {
int a, b;
};
void expand(int x, connection *&arr, std::set<int> &exp, int size) {
for (int i = 0; i < size; i++) {
if (x == arr[i].a) {
exp.insert(arr[i].b);
}
else if (x == arr[i].b) {
exp.insert(arr[i].a);
}
}
return;
}
// recursive breadth-first-seach
bool BFSr(std::set<int> &group, std::set<int> &visited, int goal, connection *&arr, int size) {
if (group.empty()) return false;
if (group.find(goal) != group.end()) return true;
std::set<int> tempa;
for (std::set<int>::iterator it = group.begin(); it != group.end(); ++it) {
expand(*it, arr, tempa size);
}
for (std::set<int>::iterator it = visited.begin(); it != visited.end(); ++it) {
tempa.erase(*it);
}
tempb = visited;
tempb.insert(group.begin(), group.end());
return BFSr(tempa, tempb, goal, arr, size);
}
bool BFS(int start, int goal, connection *&arr, int size) {
std::set<int> tempa;
std::set<int> tempb;
tempa.insert(start);
return BFSr(tempa, tempb, goal, arr, size);
}
int main()
{
connection *arr = new connection[m];
connection *con = new connection[m - 1];
// fill arr with connections arr.a < arr.b ....
for (int j = 0; j < (m - 1); j++) {
con[j] = arr[j + 1];
}
// 1. edge for performance reasons extra
if (!BFS(arr[0].a, arr[0].b, con, (m - 1))) {
// connection is important therefore add to list
printf(" %d", 1);
}
// Look if nodes still connected after removing connection
for (int s = 1; s < m; s++) {
con[s - 1] = arr[s - 1];
if (!BFS(arr[s].a, arr[s].b, con, (m-1))) {
// connection is important therefore add to list
printf(" %d", s + 1);
}
}
printf("\n");
free(arr);
free(con);
return 0;
}
Do you know any solutions for me to make it faster, or do you know a better algorithm for my problem?
An edge whose deletion disconnects two connected components is called a bridge and there are linear-time algorithms for finding all the bridges in a graph (usually based on depth-first search). The Wikipedia article lists one of them (due to Tarjan) as an example. This paper also gives a simple algorithm for listing all the bridges in a graph and seems to be a bit simpler than Tarjan's algorithm.
Hope this helps!
Here is another version of your algorithm (I guess you will get industry standard optimization implementation of graph and various algorithm for free):
I am referring to this image as graph model.
Gist (from this post)
find articulation points
all points with single out-edge are
articulation points (boost graph won't return these)- these edges
are automatically bridging edges
for each articulation point-
loop over each outedge, if outedge already not bridging edge- then
remove the edge and check for graph components and add the edge back
again
At the end it will print Edge(a,g) connects components in graph
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/biconnected_components.hpp>
#include <boost/graph/connected_components.hpp>
#include <functional>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
typedef boost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
typedef boost::graph_traits<Graph>::edge_descriptor edge_t;
// reference:
// http://lists.boost.org/boost-users/2005/08/13098.php
//
struct edge_t_hasher
{
std::size_t operator()(const edge_t& e) const
{
auto prop = e.get_property();
std::hash<decltype(prop)> hasher;
return hasher(prop);
}
};
typedef std::unordered_set<edge_t, edge_t_hasher> UnorderedBoostEdgeSet;
Graph getGraph()
{
Graph g;
vertex_t aVtx = boost::add_vertex(g);
vertex_t bVtx = boost::add_vertex(g);
vertex_t cVtx = boost::add_vertex(g);
vertex_t dVtx = boost::add_vertex(g);
vertex_t eVtx = boost::add_vertex(g);
vertex_t fVtx = boost::add_vertex(g);
vertex_t gVtx = boost::add_vertex(g);
vertex_t hVtx = boost::add_vertex(g);
vertex_t iVtx = boost::add_vertex(g);
boost::add_edge(dVtx, cVtx, g);
boost::add_edge(dVtx, bVtx, g);
boost::add_edge(cVtx, bVtx, g);
boost::add_edge(aVtx, bVtx, g);
boost::add_edge(bVtx, eVtx, g);
boost::add_edge(eVtx, fVtx, g);
boost::add_edge(aVtx, fVtx, g);
boost::add_edge(aVtx, gVtx, g);// edge connecting components
boost::add_edge(gVtx, iVtx, g);
boost::add_edge(gVtx, hVtx, g);
boost::add_edge(hVtx, iVtx, g);
return g;
}
UnorderedBoostEdgeSet bridgingEdgesForGraph(const Graph& graph)
{
UnorderedBoostEdgeSet bridgeEdges;
std::unordered_set<vertex_t> articulationVertices;
boost::articulation_points(graph, std::inserter(articulationVertices, articulationVertices.end()));
// add all the single connected vertices to the articulation vertices
auto vtxIters = boost::vertices(graph);
for (auto it = vtxIters.first, end = vtxIters.second; it != end; ++it)
{
if (boost::out_degree(*it, graph) == 1)
bridgeEdges.insert(*(boost::out_edges(*it, graph).first));
}
std::vector<vertex_t> componentsInGraph(boost::num_vertices(graph));
int numComponentsInGraph = boost::connected_components(graph, &componentsInGraph[0]);
// for each articulation vertex now get edges and check if removing that
// edge causes graph change in connected components
//
// copy the graph- so we can iterate over the outeges of vertices
// we will be fiddling with the copy- since the vtx descriptors are
// ints- they stay same across copy and removing edge operation
auto graph2 = graph;
for (auto vtx : articulationVertices)
{
auto outEdges = boost::out_edges(vtx, graph);
for (auto it = outEdges.first, end = outEdges.second; it != end; ++it)
{
auto edge = *it;
if (bridgeEdges.find(edge) != bridgeEdges.end())
continue;
// map this edge to graph2 edge- for removal and eventual addition
auto src = boost::source(edge, graph);
auto tgt = boost::target(edge, graph);
auto edge2 = boost::edge(src, tgt, graph2).first;
boost::remove_edge(edge2, graph2);
std::vector<vertex_t> componentsInGraph2(boost::num_vertices(graph2));
int numComponentsInGraph2 = boost::connected_components(graph2, &componentsInGraph2[0]);
// bridging edge- graph #components changed
if (numComponentsInGraph != numComponentsInGraph2)
bridgeEdges.insert(edge);
// add the edge back to graph2
boost::add_edge(src, tgt, graph2);
}
}
return bridgeEdges;
}
int main()
{
const Graph& graph = getGraph();
const auto& bridgingEdges = bridgingEdgesForGraph(graph);
const char* array = {"ABCDEFGHI"};
for (auto edge : bridgingEdges)
{
std::cout << "Edge(" << array[boost::source(edge, graph)] << ", " << array[boost::target(edge, graph)]
<< ") is a bridging edge" << std::endl;
}
return 0;
}
Meanwhile I found out how those special edges are called: Bridges.
And therefore I found a site giving an DFS algorithm for finding all bridges.
It's fast enough for my purposes.
DFS algorithm for finding Bridges in a undirected Graph
Thank you Sarang, your post made me find the correct search words for the site.
the problem is documented in the code, look at him. I try to push_back an edge but it is not inserted. Maybe I should initialize even the lists but I've done in the constructor and nothing changes
Here is the function where I try to add the edge to teh adjacency list:
void Graph::addEdge(int vertex1, int vertex2){
if(!adjacent(vertex1, vertex2)) // if there isn't yet a Edge
adjacency_list[vertex1].push_back(Edge(vertex2, 1)); // add this edge without weight
std::cout << Edge(vertex2, 1) << std::endl; // THE OBJECT EDJE IS PROPERLY CREATED
std::cout << adjacency_list[vertex1].size() << std::endl; // THE SIZE IS EVERYTIME 0
printlist(adjacency_list[vertex1]); // THIS FUNCTION PRINTS JUST end, IN THE LIST THERE IS NOTHING
}
And here the constructor of graph, where there is the adjacency list variable and his initialization
class Graph{
public:
//Graph constructor that takes as parameter the number of vertices in the Graph
Graph(int NumberOfVertices):vertices(NumberOfVertices),
edges(0),
adjacency_list(NumberOfVertices){
for(int x = 0; x < numberOfVertices; x++) adjacency_list[x] = std::list<Edge>();
};
~Graph() { adjacency_list.clear(); }
int V() const { return vertices; }
int E() const { return edges; }
Edge returnEdge(std::list<Edge> list, const int vertex2);
bool adjacent (int vertex1, int vertex2);
std::list<Edge> neighbors(int vertex1) const;
void addEdge(int vertex1, int vertex2);
Edge *deleteFromList(Edge *list, const int vertex2);
void deleteEdge(int vertex1, int vertex2);
int getEdgeWeight(int vertex1, int vertex2);
void setEdgeWeight(int vertex1, int vertex2, int weight);
int incrementEdges() { edges++; } //increment by 1 the number of edges
private: int vertices, //number of vertices
edges; //number of edges
std::vector<std::list<Edge> > adjacency_list; //adjacency_list: every element of index x the vector is a list of edges from x
};
I'm wondering if I should initialize every lists in the adjacency_list vector but I don't know how to do that. How can I fix the problem?
There is a possible out-of-range problem in the line adjacency_list[vertex1].push_back(Edge(vertex2, 1)); Namely operator[] does not signal if the requested index is out of range. To resolve this issue you can
check the maximum index for adjacency_list vector by adjacency_list.max_size() method and then resize the vector, if necessary, using adjacency_list.resize() or
use adjacency_list.at() to index the vector but check for the out-of-range exception.
For the performance reason it would be the most convenient to build the large enough vector at the beginning.
Yet another way could be to use map<list<Edge> > (or unordered_map) instead of vector.