Cannot get "stack" to populate in DFS based task ordering program - c++

I am writing a program that uses the recursive BFS algorithm to determine dependencies in an undirected graph. I am using a 5x5 array as an adjacency matrix to represent the graph. While debugging, I noticed that my "stack s" variable is remaining empty while running and I cannot figure where the logical error is. Please note that I am new to programming and if I have made any fundamental mistakes or misunderstandings in the code please let me know.
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
void TaskOrderHelper(int A[5][5], int start, vector<bool> visited, stack<int> s)
{
for(int i = 0; i < 5; i++)
{
if(A[start][i] == 1 && visited[i] == false)
{
visited[i] = true;
TaskOrderHelper(A, i, visited, s);
s.push(i);
}
}
}
vector<int> taskOrder(int A[5][5], int start)
{
vector<bool> visited(5,false);
stack<int> s;
vector<int> result;
for(int i = 0; i < 5; i++)
{
visited[i] = true;
}
visited[start] = true;
TaskOrderHelper(A, start, visited, s);
while(!s.empty())
{
int w = s.top();
result.push_back(w);
s.pop();
}
return result;
}
int main()
{
int A[5][5] =
{
{0,1,1,0,0},
{1,0,0,1,0},
{1,0,0,0,1},
{0,1,0,0,1},
{0,0,1,1,0}
};
vector<int> result = taskOrder(A, 0);
for(auto i: result)
{
cout << i;
}
return 0;
}

Line 26 you set visited[i] = true; for all visiteds, your recursive if statement never hits

There are other issues here with the BFS but to answer your question on why your stack is empty, your stack is being passed by value, to modify a parameter passed into another function you'll want to pass by reference. Try changing TaskOrderHelper to
void TaskOrderHelper(int A[5][5], int start, vector<bool>& visited, stack<int>& s)

Related

Finding maximum clique with node count and nonadjacent edge list given

I have a task which I have been trying to solve for the last week. It's driving me crazy. The task is:
Given a node count N(1 <= N <= 10`000),
nonadjacent node pair count M(1 <= M <= 200`000)
and the nonadjacent node pairs themselves
M0A, M0B,
M1A, M1B,
...
MM-1A, MM-1B,
find the maximum clique.
I am currently trying all kinds of bron-kerbosch algorithm variations.
But every time I get a time limit on the testing site. I posted the only code that doesn't have a time limit BUT it has a wrong answer. The code is kind of optimized by not creating a new set every recursion.
Anyways, PLEASE help me. I am a desperate latvian teen programmer. I know this problem can be solved, because many people have solved it on the testing site.
#include <set>
#include <vector>
std::map<int, std::set<int> > NotAdjacent;
unsigned int MaxCliqueSize = 0;
void PrintSet(std::set<int> &s){
for(auto it = s.begin(); it!=s.end(); it++){
printf("%d ",*it);
}
printf("\n");
}
void Check(std::set<int> &clique, std::set<int> &left){
//printf("printing clique: \n");
//PrintSet(clique);
//printf("printing left: \n");
//PrintSet(left);
if(left.empty()){
//PrintSet(clique);
if(clique.size()>MaxCliqueSize){
MaxCliqueSize = clique.size();
}
return;
}
while(left.empty()==false){
std::vector<int> removed;
int v = *left.begin();
left.erase(left.begin());
for(auto it2=NotAdjacent[v].begin();it2!=NotAdjacent[v].end();it2++){
auto findResult = left.find(*it2);
if(findResult!=left.end()){
removed.push_back(*it2);
left.erase(findResult);
}
}
clique.insert(v);
Check(clique, left);
clique.erase(v);
for(unsigned int i=0;i<removed.size();i++){
left.insert(removed[i]);
}
}
}
int main(){
int n, m;
scanf("%d%d",&n,&m);
int a, b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
NotAdjacent[a].insert(b);
NotAdjacent[b].insert(a);
}
std::set<int> clique, left;
for(int i=1;i<=n;i++){
left.insert(i);
}
Check(clique, left);
printf("%d",MaxCliqueSize);
}
For what it's worth, this code seems to pass 5 tests and I think all the rest exceed either time or memory limits (submitted as C++11). This idea is to find a maximum independent set in the graph complement, for which we readily receive the edges for. The algorithm is what I could understand of the standard greedy one. Perhaps this can give you or others more ideas? I believe there are some improved algorithms for MIS.
#include <iostream>
using namespace std;
#include <map>
#include <set>
#include <vector>
#include <algorithm>
std::map<int, std::set<int> > NotAdjacent;
vector<int> Order;
unsigned int NumConnectedToAll = 0;
unsigned int MaxCliqueSize = 0;
bool sortbyN(int a, int b){
return (NotAdjacent[a].size() > NotAdjacent[b].size());
}
void mis(std::set<int> &g, unsigned int i, unsigned int size){
if (g.empty() || i == Order.size()){
if (size + NumConnectedToAll > MaxCliqueSize)
MaxCliqueSize = size + NumConnectedToAll;
return;
}
if (g.size() + size + NumConnectedToAll <= MaxCliqueSize)
return;
while (i < Order.size() && g.find(Order[i]) == g.end())
i++;
int v = Order[i];
std::set<int> _g;
_g = g;
_g.erase(v);
for (auto elem : NotAdjacent[v])
_g.erase(elem);
mis(_g, i + 1, size + 1);
}
int main(){
int n, m;
scanf("%d%d",&n,&m);
int a, b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
NotAdjacent[a].insert(b);
NotAdjacent[b].insert(a);
}
std::set<int> g;
Order.reserve(NotAdjacent.size());
for (auto const& imap: NotAdjacent){
Order.push_back(imap.first);
g.insert(imap.first);
}
sort(Order.begin(), Order.end(), sortbyN);
for (int i=1; i<=n; i++)
if (NotAdjacent.find(i) == NotAdjacent.end())
NumConnectedToAll++;
for (unsigned int i=0; i<Order.size(); i++){
mis(g, i, 0);
g.erase(Order[i]);
}
printf ("%d", MaxCliqueSize);
return 0;
}

Error while Compiling "|75|error: cannot convert 'std::vector<int>' to 'int'" while implementing bfs

I am implementing bfs (Breadth First Search ) for the graph , but I am getting an error while I pass the starting value of the vector to an integer, for the dfs function to perform, as in the dfs function I have passed the source of the vector, i.e the first element of the vector.
error is on the line where start is declared to v[i]
Here is the complete code
#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
using namespace std;
vector<int> v[10];
bool visited[10];
int level[10];
int a = 0;
int arr[10];
void dfs(int s) //function should run only one time
{
queue<int> q;
q.push(s);
visited[s] = true;
level[s] = 0;
while (!q.empty())
{
int p = q.front();
arr[a] = p;
a++;
q.pop();
for (int i = 0; i < v[p].size(); i++)
{
if (visited[v[p][i]] == false) {
level[v[p][i]] = level[p] + 1;
q.push(v[p][i]);
visited[v[p][i]] = true;
}
}
}
}
int main()
{
char c;
int start; // starting element of the vector
int i = 0; // for keeping track of the parent
int countt = 0; // keep track of the no of parents
bool check;
printf("Child or Parent ?");
scanf("%c", &c);
while (countt <= 10) {
if (c == 'c') {
check = true;
int j = 0;
while (check) {
// to keep the track of the child;
scanf("%d", &v[i][j]);
j++;
}
}
if (c == 'p')
{
scanf("%d", &v[i]);
if (i == 0)
{
start = v[i];
}
i++;
countt++;
}
}
printf(" Vector input completed");
dfs(start);
printf("DFS completed, printing the dfs now ");
for (int g = 0; g <= 10; g++)
{
printf("%d", &arr[g]);
}
}
In your current code, v is an array of size 10 containing vector's. However, start is an int, so there is nothing strange in getting an error when trying to assign one to another.
I believe that you wanted v to be either an array of ints or vector of ints. In such a case you just have to declare v properly: int v[10] or vector<int> v(10).
This is general syntax: if you want to declare a vector with known size then you have to put it in (), not in []. Note that you can also fill the vector with some initial values (say zeroes) by writing vector<int> v(10, 0).
In case got you wrong and you wanted to store a graph as vector of vectors, then you can write vector<vector<int>> v(10).

How to write code for Breadth-first search in C++

I have been trying to do a graph search for a problem from Hackerrank. Lastly, I have come up with
#include <cstdio>
#include <list>
using namespace std;
void bfs(list<int> adjacencyList[], int start, int countVertices) {
// initialize distance[]
int distance[countVertices];
for(int i=0;i < countVertices; i++) {
distance[i] = -1;
}
list<int>::iterator itr;
int lev = 0;
distance[start-1] = lev; // distance for the start vertex is 0
// using start -1 since distance is array which are 0-indexed
list<int> VertexQueue;
VertexQueue.push_back(start);
while(!VertexQueue.empty()) {
int neighbour = VertexQueue.front();
itr = adjacencyList[neighbour].begin();
while(itr != adjacencyList[neighbour].end()) {
int vertexInd = (*itr) - 1;
if(distance[vertexInd] == -1) { // a distance of -1 implies that the vertex is unexplored
distance[vertexInd] = (lev + 1) * 6;
VertexQueue.push_back(*itr);
}
itr++;
}
VertexQueue.pop_front();
lev++;
}
// print the result
for(int k=0;k< countVertices;k++) {
if (k==start-1) continue; // skip the start node
printf("%d ",distance[k]);
}
}
int main() {
int countVertices,countEdges,start,T,v1,v2;
scanf("%d", &T);
for(int i=0; i<T; i++) {
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
// input edges in graph
for(int j=0; j<countEdges; j++) {
scanf("%d%d",&v1,&v2);
adjacencyList[v1].push_back(v2);
adjacencyList[v2].push_back(v1); // since the graph is undirected
}
scanf("%d",&start);
bfs(adjacencyList, start, countVertices);
printf("\n");
}
return 0;
}
However, this is resulting in 'Segmentation Fault' and I cannot figure out where I am going wrong.
Also, I have comes across segmentation fault a lot of times, but have no idea how to debug it. Would be great if someone can give me an idea of that.
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
Above code appears wrong. If your indices start with 1, either make adjacencyList of size countVertices + 1 or decrease u and v before putting them in the list.
You can also use a (an unordered) map mapping vertex to a list which will not segfault.
Also not that VLA are not part of standard C++, so avoid them even if your compiler support them as extension.

RunTime Error - Tree isomorphism

In this code I want to check whether two trees are isomorphic or not.
The algorithm that I've used is to get two strings with the help of DFS algorithm, sorting them and then comparing them.
This code works in visual studio 2010 but when I try to submit in UVA online judge I keep getting the Run Time Error and since I'm not a professional programmer I can't understand why.
I was also trying to optimize my code so I used short instead of int and scanf - printf instead of cin and cout.
I would appreciate some help on how to fix my code and also how to optimize it.
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef vector<short> vi;
typedef vector<vi> vvi;
short V=0; // number of vertices for the trees.
string str;
string strrr;
short max1=0;
short max2=0;
short temp=0;
short GetDeg1(vvi t1, short n1) // for the first tree
{
vi deg(n1+1);
for( short i=1; i<n1+1 ;i++) // to make a vector named deg that has the degree of each vertex
{
deg[i]= t1[i].size();
if(deg[i]>max1)
{
temp=i; // temp has the index of the vertex with the maximum degree
max1=deg[i];
}
}
return temp;
}
short GetDeg2(vvi t2, short n2) // for the second tree
{
vi deg(n2+1);
for( short i=1; i<n2+1 ;i++)
{
deg[i]= t2[i].size();
if( deg[i]>max2)
{
temp=i;
max2=deg[i];
}
}
return temp;
}
string DFSUtil(vvi t ,short v, bool visited[])
{
visited[v] = true; // Mark the current node as visited
// Recur for all the vertices adjacent to this vertex
vector<string >strnode ;
for(short i = 0 ; i< (short)(t[v].size() ); ++i)
{
if(!visited[t[v][i]])
{ string a;
a = DFSUtil(t, t[v][i], visited);
strnode.push_back(a) ;
}
}
sort (strnode.begin(), strnode.end());
str="(";
for(short t=0; t< (short)(strnode.size()); t++)
str+= strnode[t];
str+=")";
return str;
}
string DFS(vvi t, short v)
{
bool *visited = new bool[V+1]; // Mark all the vertices as not visited
for(short i = 1; i < V+1; i++)
visited[i] = false;
strrr= DFSUtil(t, v, visited); // Call the recursive helper function to print DFS traversal
return strrr;
}
int main()
{
while(cin>>V)
{
max1=0;
max2=0;
temp=0;
string str1;
string str2;
strrr.clear();
str1.clear();
str2.clear();
str.clear();
short v1 ;
short v2;
vvi Tree1(V+1);
for( short i=0; i<V-1; i++)
{
scanf("%d",&v1);
scanf("%d",&v2);
Tree1[v1].push_back(v2);
Tree1[v2].push_back(v1);
}
vvi Tree2(V+1);
for( short i=0; i<V-1; i++)
{
scanf("%d",&v1);
scanf("%d",&v2);
Tree2[v1].push_back(v2);
Tree2[v2].push_back(v1);
}
cout<<endl;
short temp1=0;
short temp2=0;
temp1= GetDeg1(Tree1, V);
temp=0;
temp2= GetDeg2(Tree2, V);
str1=DFS(Tree1, temp1);
str.clear();
strrr.clear();
str2=DFS(Tree2, temp2);
if( str1.compare(str2) == 0)
printf("S\n");
else
printf("N\n");
}
return 0;
}

N Queens in C++ using vectors

I'm having trouble understanding backtracking, I can conceptually understand that we make a move, then if no solutions can be found out of it we try the next solution.
With this in mind I'm trying to solve the N Queens problem,
I'm finding out all the possible candidates that can be placed in the next row and then trying them one by one, if a candidate doesn't yield a solution, I pop it off and go with the next one.
This is core of the code that I have come up with :
void n_queens(int n)
{
vector<int> queens = vector<int>();
backtrack(queens,0,n);
}
void backtrack(vector<int>& queens, int current_row, int N)
{
// check if the configuration is solved
if(is_solution(queens, N))
{
print_solution(queens,N);
}
else
{
// construct a vector of valid candidates
vector<int> candidates = vector<int>();
if(construct_candidates(queens,current_row,N,candidates))
{
for(int i=0; i < candidates.size(); ++i)
{
// Push this in the partial solution and move further
queens.push_back(candidates[i]);
backtrack(queens,current_row + 1,N);
// If no feasible solution was found then we ought to remove this and try the next one
queens.pop_back();
}
}
}
}
bool construct_candidates(const vector<int>& queens, int row, int N, vector<int>& candidates)
{
// Returns false if there are no possible candidates, we must follow a different
// branch if this so happens
for(int i=0; i<N; ++i)
{
if(is_safe_square(queens,row,i,N))
{
// Add a valid candidate, this can be done since we pass candidates by reference
candidates.push_back(i);
}
}
return candidates.size() > 0;
}
It doesn't print anything for any input that I give it. I tried running it through gdb but with no success, I think that is because there is a problem with my fundamental understanding of backtracking.
I have read up about backtracking in a couple of books and also an online tutorial and I still feel hazy, it'd be nice if someone could give me ideas to approach this and help me understand this slightly unintuitive concept.
The entire compilable source code is :
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// The method prototypes
void n_queens(int n);
void backtrack(vector<int>&, int current_row, int N);
bool construct_candidates(const vector<int>&, int row, int N, vector<int>&);
bool is_safe_square(const vector<int>&, int row, int col, int N);
bool is_solution(const vector<int>&, int N);
void print_solution(const vector<int>&, int N);
int main()
{
int n;
cin>>n;
n_queens(n);
return 0;
}
void n_queens(int n)
{
vector<int> queens = vector<int>();
backtrack(queens,0,n);
}
void backtrack(vector<int>& queens, int current_row, int N)
{
// check if the configuration is solved
if(is_solution(queens, N))
{
print_solution(queens,N);
}
else
{
// construct a vector of valid candidates
vector<int> candidates = vector<int>();
if(construct_candidates(queens,current_row,N,candidates))
{
for(int i=0; i < candidates.size(); ++i)
{
// Push this in the partial solution and move further
queens.push_back(candidates[i]);
backtrack(queens,current_row + 1,N);
// If no feasible solution was found then we ought to remove this and try the next one
queens.pop_back();
}
}
}
}
bool construct_candidates(const vector<int>& queens, int row, int N, vector<int>& candidates)
{
// Returns false if there are no possible candidates, we must follow a different
// branch if this so happens
for(int i=0; i<N; ++i)
{
if(is_safe_square(queens,row,i,N))
{
// Add a valid candidate, this can be done since we pass candidates by reference
candidates.push_back(i);
}
}
return candidates.size() > 0;
}
bool is_safe_square(const vector<int>& queens, int row, int col, int N)
{
for(int i=0; i<queens.size(); ++i)
{
// case when the queens are already placed in the same row or column
if(queens[i] == row || queens[i] == col) return false;
// case when there is a diagonal threat
// remember! y = mx + c for a diagonal m = 1 therefore |x2 - x1| = |y2 - y1|
if(abs(i - row) == abs(queens[i] - col)) return false;
}
//Returns true when no unsafe square is found
//handles the case when there are no queens on the board trivially
return true;
}
bool is_solution(const vector<int>& queens, int N)
{
return queens.size() == N;
}
void print_solution(const vector<int>& queens, int N)
{
for(int i=0; i<N; ++i)
{
for(int j=0; j<N; ++j)
{
if(queens[i] == j){ cout<<'Q'; }
else { cout<<'_'; }
}
cout<<endl;
}
}
It's not a fundamental problem, it's just a bug.
In is_safe_square, change
queens[i] == row
to
i == row