Segmentation fault , while accepting graph inputs from input file - c++

I am writing a program to find out "Strongly Connected Component" of a given graph.
For that I am using following algorithm.
1) Apply DFS and push the nodes in decreasing order of their Finishing time in stack.
2) Transpose the graph. ( reverse the edges of the graph)
3) Pop the node and apply DFS again.
For this if I accept the graph edges by function addEdge(int u, int v) (edge from node u to node v).
then program works correctly.
Question : But when I try to accept graph through input file, it is giving me error.
I am not giving whole program as it is working correctly.
class Graph
{
int V;
list<int> *adj;
void fillorder( int v , bool visited[] , stack<int> &stack);
void DFSUtil(int v , bool visited[]);
public:
Graph( int V);
void printSCCs();
Graph get_Transpose();
void print_graph();
void read_input_file();
};
Graph:: Graph(int V)
{
this-> V = V;
adj = new list<int>[V];
}
void Graph :: read_input_file()
{
const long int N = 100;
std::ifstream infile("S.txt");
std::string line;
int i = 0;
while ( i < N && getline(infile, line) )
{
std::istringstream str(line);
int u;
str >> u;
if ( u > N )
{
// Problem.
abort();
}
int v;
while ( str >> v )
{
adj[u-1].push_back(v);
}
++i;
}
}
void Graph :: print_graph()
{
for( int i = 0 ; i < 9 ; i++ )
{
list<int> :: iterator itr;
for( itr = adj[i].begin(); itr != adj[i].end(); ++itr )
{
cout<< i+1 <<" --> " << *itr <<endl;
}
}
}
void Graph:: printSCCs()
{
stack<int>Stack;
bool *visited = new bool[V];
for( int i = 0 ; i < V ; i++ )
visited[i] = false;
for( int i = 0 ; i < V ; i++ )
if(visited[i] == false)
fillorder(i , visited , Stack);
Graph gr = get_Transpose();
for( int i = 0 ; i < V ; i++ )
visited[i] = false;
while( Stack.empty() == false)
{
int no = Stack.top();
Stack.pop();
if(visited[no] == false)
{
gr.DFSUtil(no , visited);
cout<< endl;
}
}
}
int main()
{
Graph g(9);
g.read_file(); // Working perfectly
g.print_graph(); // showing graph perfectly
g.printSCCs(); // Giving error : Segmentation fault: core dump
return 0;
}
Graph is getting printed correctly but g.printSCCs() is not working.
Error is : Segmentation fault: core dump
Now if g.print_graph() is working perfectly then why not g.printSCCs() ?
NOTE : I have not pasted whole program just to insure that it will be readable.
Moreover , by manually entering edges , whole program works perfectly , so I think there will not be error in any function.
I/P file data :
1 4
2 8
3 6
4 7
5 2
6 9
7 1
8 5
8 6
9 7
9 3

Related

getting segmentation error on Kruskal algorithm for mst in gfg practice

vector<int> pr;
vector<int> sz;
vector<vector<int>> ans;
void mset(int u)
{
pr[u] = u ;
sz[u] = 1;
}
int fset(int u)
{
if(pr[u] == u)
return u;
return pr[u] = fset(pr[u]);
}
void uset(int u , int v)
{
u = fset(u);
v = fset(v);
if(u != v)
{
if(sz[u] < sz[v])
swap(u , v);
sz[u] += sz[v];
pr[v] = pr[u];
}
}
int com(vector<int> a , vector<int> b)
{
return a[0] > b[0];
}
int spanningTree(int V, vector<vector<int>> adj[])
{
// code here
for(int i = 0 ; i < V ; i++)
{
mset(i);
}
int cost = 0;
for(int i = 0 ; i < V ;i++)
{
for(auto j : adj[i] )
{
ans.push_back( {j[1],j[0],i} );
}
}
sort(ans.begin() , ans.end());
for(auto i : ans )
{
int w = i[0];
int u = i[1];
int v = i[2];
u = fset(u);
v = fset(v);
if(v == u)
{
continue ;
}
else
{
cost += w;
uset(u , v);
}
}
return cost ;
}
// i was trying to do mst using Kruskal algo on gfg practice , there the graph (weighted) was implemented using array of 2d vector , so i tried to convert it into a 2d vector having first element as weight so that it can easily get sorted when using sort() function but i am getting segmentation fault , i dont know what is the bug .... plz help find the problem in code .

How to modify Disjktra algorithm to have at least X vertices or K edges in shortest path

I have this Dijkstra algorithm although I want to modify it or is it possible to do it with another algorithm ?
I need to output the vertices of the shortest path, although I need to have at least 5 vertices (>=5 vertices) to the shortest path from start node to end node.
At the end of the code you'll see the Dijkstra algorithm so I would need to modify it so I could add a variable where I need to have at least X(5in my case) vertices.
#include<iostream>
#include<set>
#include<list>
#include<algorithm>
using namespace std;
typedef struct nodes {
int dest;
double cost;
}node;
class Graph{
int n;
list<node> *adjList;
private:
void showList(int src, list<node> lt) {
list<node> :: iterator i;
node tempNode;
for(i = lt.begin(); i != lt.end(); i++) {
tempNode = *i;
cout << "(" << src << ")---("<<tempNode.dest << "|"<<tempNode.cost<<") ";
}
cout << endl;
}
public:
Graph() {
n = 0;
}
Graph(int nodeCount) {
n = nodeCount;
adjList = new list<node>[n];
}
void addEdge(int source, int dest, double cost) {
node newNode;
newNode.dest = dest;
newNode.cost = cost;
adjList[source].push_back(newNode);
}
void displayEdges() {
for(int i = 0; i<n; i++) {
list<node> tempList = adjList[i];
showList(i, tempList);
}
}
friend void dijkstra(Graph g, double *dist, int *prev, int start);
};
void dijkstra(Graph g, double *dist, int *prev, int start) {
int n = g.n;
for(int u = 0; u<n; u++) {
dist[u] = 9999; //set as infinity
prev[u] = -1; //undefined previous
}
dist[start] = 0; //distance of start is 0
set<int> S; //create empty set S
list<int> Q;
for(int u = 0; u<n; u++) {
Q.push_back(u); //add each node into queue
}
while(!Q.empty()) {
list<int> :: iterator i;
i = min_element(Q.begin(), Q.end());
int u = *i; //the minimum element from queue
Q.remove(u);
S.insert(u); //add u in the set
list<node> :: iterator it;
for(it = g.adjList[u].begin(); it != g.adjList[u].end();it++) {
if((dist[u]+(it->cost)) < dist[it->dest]) { //relax (u,v)
dist[it->dest] = (dist[u]+(it->cost));
prev[it->dest] = u;
}
}
}
}
Thank you for your help
Disjktra algorithm works with status, normally the status is only the node as you use in your code, but can be modified for anothers use cases as this. You use dist[n] representing distance to reach node n, but you can modify it as dist[n][m] to represent distance to reach node n with exactly m nodes in path. The first problem that you can see is that if the max number of nodes >= 10^5 by example, you can't represent it in a matrix. So, the first optimization is use m=5, where for 1 <= m <= 4 represent exactly m nodes in path, but m = 5 is at least 5 nodes in path, more is not interesting for the problem.
void dijkstra(Graph g, double **dist, pair<int, int> **prev, int start) {
int n = g.n;
for(int u = 0; u<n; u++) {
for(int v = 1; v <= 5; v++) {
dist[u][v] = 9999999; //set as infinity
prev[u][v] = -1; //undefined previous
}
}
dist[start][1] = 0; //distance of start is 0
priority_queue<pair<double, pair<int, int> > > Q;
Q.push(make_pair(0, make_pair(start, 1)));
while(!Q.empty()) {
pair<double, pair<int, int> > > top = Q.top(), Q.pop();
u = top.second.firt;
v = top.second.second;
for(it = g.adjList[u].begin(); it != g.adjList[u].end();it++) {
int w = (v == 5)? v : v + 1;
if((dist[u][v]+(it->cost)) < dist[it->dest][w]) { //relax (u,v)
dist[it->dest][w] = (dist[u][v]+(it->cost));
prev[it->dest][w] = make_pair(u, v);
Q.push(make_pair(-dist[it->dest][w], make_pair(it->dest, w))); // negative distance to reverse priority queue order
}
}
}
}
I did some modifications, as use a priority_queue, I think that is a simple solution for same problem.
PD: Maybe I wrote some mistakes, I haven't a compiler now to test. Sorry my english mistakes.

How to erase all elements from a vector except for the largest in a specific range?

Suppose I have the following vector:
The vector is a vector of pairs, and we are comparing based on the first element.
[(1,0),(0,1),(3,2),(6,3),(2,4),(4,5),(7,6),(5,7)]
I want to erase all elements in a specific range except the largest.
For example, if the range was $l = 2$ and $r = 5$, then the output:
[(1,0),(0,1),(6,3),(7,6),(5,7)]
Now if we do this again to the output array for $l = 1$, $r = 4$, then the output:
[(1,0),(7,6)]
I found this which I thought would be useful here, but I don't know how to make it work for pairs.
Here is my attempt:
int main(int argc, char const *argv[]) {
int N;
cin >> N;
vector< pair<int,int> > vector_of_pairs(N);
for (int i = 0; i < N; i++) {
int input;
cin >> input;
vector_of_pairs[i] = make_pair(input, i);
}
int l, r;
cin >> l >> r;
int max_in_range = vector_of_pairs[l].first;
for (int i = l+1; i <= r; i++) {
if (vector_of_pairs[i].first > max_in_range) {
max_in_range = vector_of_pairs[i].first;
}
}
for (int i = l; i <= r; i++) {
if (vector_of_pairs[i].first != max_in_range) {
vector_of_pairs.erase(vector_of_pairs.begin() + i);
}
}
printf("[");
for(int i = 0; i < vector_of_pairs.size(); i++) {
printf("(%d,%d)", vector_of_pairs[i].first, vector_of_pairs[i].second);
}
printf("]\n");
}
For the following input:
8
1 0 5 6 2 3 7 4
1 3
This is the output:
[(1,0)(5,2)(6,3)(3,5)(7,6)(4,7)]
But it should be
[(1,0)(6,3)(3,5)(7,6)(4,7)]
Also, for certain inputs I get seg faults so how can I safe guard against that?
Erase remove idiom at the rescue:
auto begin = v.begin() + l;
auto end = v.begin() + r + 1;
auto max_value = *std::max_element(begin, end);
v.erase(std::remove_if(begin, end,
[&](const auto& p) {return p.first != max_value.first; }),
end);
Demo
Probabaly you want this
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char const *argv[]) {
int N;
cin >> N;
vector< pair<int,int> > vector_of_pairs(N);
for (int i = 0; i < N; i++) {
int input;
cin >> input;
vector_of_pairs[i] = make_pair(input, i);
}
int l, r;
cin >> l >> r;
int max_in_range = vector_of_pairs[l].first;
for (int i = l+1; i <= r; i++) {
if (vector_of_pairs[i].first > max_in_range) {
max_in_range = vector_of_pairs[i].first;
}
}
int p=l;
for (int i = l; i <= r;i++ ) {
if (vector_of_pairs[p].first != max_in_range) {
vector_of_pairs.erase(vector_of_pairs.begin()+p);
}
else p++;
}
printf("[");
for(int i = 0; i < vector_of_pairs.size(); i++) {
printf("(%d,%d)", vector_of_pairs[i].first, vector_of_pairs[i].second);
}
printf("]\n");
}
Getting correct output :
[(1,0)(6,3)(2,4)(3,5)(7,6)(4,7)]
Explanation: When you delete an item in vector, items present after the deleted element get decreased their index by 1. Hence in the ith loop from l to r you shouldn't delete vec.begin()+i element, instead delete vec.begin()+l item until you find largest element, and delete vec.begin()+l+1 element after you find largest element.
Hope it helps.
If you don't need a stable algorithm you can simply sort the vector, get iterator for l in begin - end, get iterator for r in l - end and then remove all but the very last element between both found iterators.
#include <algorithm>
template<class V, class T>
void remove_range_but_max(V& vop, T const& l, T const& r)
{
std::sort(vop.begin(), vop.end());
auto lo = std::lower_bound(vop.begin(), vop.end(), l);
auto hi = std::lower_bound(lo, vop.end(), r);
if(hi != lo) --hi;
vop.erase(lo, hi);
}
can be used like:
std::vector< std::pair< int , int > > input {
std::make_pair( 1 , 0 ) , std::make_pair( 0 , 1 ) ,
std::make_pair( 3 , 2 ) , std::make_pair( 6 , 3 ) ,
std::make_pair( 2 , 4 ) , std::make_pair( 4 , 5 ) ,
std::make_pair( 7 , 6 ) , std::make_pair( 5 , 7 ) };
/* remove all pairs in range [(2,0), (6,0)) */
remove_range_but_max(input, std::make_pair(2,0), std::make_pair(6,0));
for(auto&& p : input) std::cout << p.first << ", " << p.second << "\n";
Prints:
0, 1
1, 0
5, 7
6, 3
7, 6
Quick and sleazy way:
std::sort(vector_of_pairs.begin(), vector_of_pairs.end());
vector_of_pairs.resize(1);
Just be sure to supply sort with the appropriate function to make the largest element get pushed to the first of the list.
Let me spell it out for you:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool i_said_to_do_this(const pair<int, int> &lhs, const pair<int, int> &rhs) {
return lhs.first > rhs.first;
}
int main(int argc, char const *argv[]) {
int pairs[][2] = {{1,0},{0,1},{3,2},{6,3},{2,4},{4,5},{7,6},{5,7}};
vector< pair<int,int> > vector_of_pairs(8);
for (int i{0}; i < 8; i++) {
vector_of_pairs[i] = make_pair(pairs[i][0], pairs[i][1]);
}
std::sort(vector_of_pairs.begin(), vector_of_pairs.end(), i_said_to_do_this);
vector_of_pairs.erase(vector_of_pairs.begin() + 1, vector_of_pairs.end());
cout << "(" << vector_of_pairs[0].first << ", " << vector_of_pairs[0].second << ")" << endl;
}

Getting run time error for Depth first search in c++ code

I have an un-directed graph. I am trying to find the maximum node value other than the adjacent ones of a given node.
For example :
6 // number of nodes
1 3
2 3
3 4
4 5
4 6// edges
I have to find the maximum node value other than the direct adjacent nodes for the node in question.
For example, if I use DFS(1) the answer must be 6. My code is working perfectly fine but if I call DFS() multiple times in suffering run time error.
#include<iostream>
#include<stack>
#include<list>
#include<map>
#include<utility>
#include<vector>
class graph
{
std::list<int> *adj;
int V;
public:
graph(int V);
void add(int v, int w);
void DFS(int s);
};
int max = -1;
graph::graph(int V)
{
this->V = V;
adj = new std::list<int>[V];
}
void graph::add(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v);
}
void graph::DFS(int s)
{
std::vector<int> visited(V, false);
std::stack<int> st;
st.push(s);
while (!st.empty())
{
int t = st.top();
st.pop();
if (!visited[t])
{
visited[t] = true;
}
for (auto i = adj[t].begin(); i != adj[t].end(); i++)
{
if (!visited[*i])
{
visited[*i] = true;
}
}
for (int j = V; j >= 0; j--)
{
if (visited[j] == 0)
{
std::cout << j << " ";
break;
}
}
}
}
int main()
{
int t = 0, k = 0;
graph g(6);
g.add(1, 3);
g.add(2, 3);
g.add(3, 4);
g.add(4, 5);
g.add(5, 6);
g.DFS(1);
g.DFS(2);
g.DFS(3);
return 0;
}

Timestamping the DFS

#include <iostream>
#include <vector>
#include <list>
using namespace std ;
class Graph
{
public:
Graph(int V)
{
this->V = V ;
G.resize(V) ;
}
void addEdge(int v , int w)
{
G[v].push_back(w) ;
G[w].push_back(v) ;
}
void DFS( int s )
{
bool *visited = new bool[this->V] ;
for( int i = 0 ; i < this->V ; i++ )
visited[i] = false ;
int *arrival = new int[this->V] ;
int *departure = new int[this->V] ;
static int t = 0 ;
DFSUtil(s,visited,arrival,departure,t) ; // Utility function to do the DFS
cout << "\n" ;
for( int i = 0 ; i < this->V ; i++ )
cout << arrival[i] << "/" << departure[i] << " " ;
}
void printGraph()
{
vector< list<int> >::iterator i ;
list<int>::iterator j ;
int k = 0 ;
int t = 0 ;
for( i = G.begin() ; i != G.end() ; ++i )
{
cout << "Node " << k++ << "->" ;
for( j = G[t].begin() ; j != G[t].end() ; ++j )
cout << *j << "->" ;
cout << "NULL\n" ;
t++ ;
}
}
private:
int V ; // number of vertices
vector< list<int> > G ; // array of lists
void DFSUtil( int s , bool *visited , int *arrival , int *departure , int t ) // Utility function to do DFS
{
cout << s << " " ;
visited[s] = true ;
arrival[s] = ++t ;
list<int>::iterator i ;
for( i = G[s].begin() ; i != G[s].end() ; ++i )
{
if( !visited[*i] )
DFSUtil(*i,visited,arrival,departure,t) ;
}
departure[s] = ++t ;
}
};
int main()
{
// Create a graph given in the above diagram
Graph g(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(0, 4);
g.addEdge(0, 3);
g.addEdge(1, 4);
g.addEdge(1, 5);
g.addEdge(4, 5);
g.addEdge(3, 5);
g.printGraph() ;
cout << "Following is Depth First Traversal (starting from vertex 0) \n";
g.DFS(0);
return 0;
}
I wanted to timestamp the process of DFS ie when the search process reaches a particular node and then bactracks from it . What I mean is that when DFS begins it first visits node 0 so arrival[0] = 1 , then it recursively calls on node 1 so arrival[1] = 2 , then recursively calls on node 2 so arrival[2] = 3 , now node 2 can't call on anyone so departure[2] should be 4 and subsequently , but what my program outputs is not on the same lines as I was expecting . I thought declaring timestamp variable t as static would do the trick , but it's not working . How to correct it ?
"static" in this context essentially means "there is only one of these that is shared by all invokations of this function".
You're still passing a copy of the variable as a parameter to the other functions.
If you want a called function to be able to modify a variable, you pass it a reference to that variable.
Remove the "static", and change DFSUtil to
void DFSUtil(int s, bool *visited, int *arrival, int *departure, int &t)