Segmentation fault while doing DFS on a coloured graph - c++

Here is my Code:
#include <bits/stdc++.h>
using namespace std;
#define limt 101
//edge stores the edges for each node
//since it is defined outside main, i don't think it is the cause for
//segmentation fault
vector<int> edge[limt][limt];
int vist[limt], tgt;
//dfs call for a node numbered <i>u</i>
//and for only the edges colored <i>c</i>
int dfs(int u, int c)
{
if (u == tgt) return 1;
vist[u] = 1;
for (int i = 0; i < edge[u][c].size(); ++i) {
if (dfs(edge[u][c][i], c)) return 1;
}
vist[u] = 0;
return 0;
}
int main()
{
//n : number of nodes
//m: number of edges
//c: color of edge
int n, m;
int u, v, c;
cin >> n >> m;
for (int i = 0; i < m; ++i) {
cin >> u >> v >> c;
edge[u][c].push_back(v);
edge[v][c].push_back(u);
}
//q: number of queries/test-cases
int q, x, y;
cin >> q;
while (q--) {
cin >> x >> y;
memset(vist, 0, sizeof(vist));
int ans = 0;
vist[x] = 1;
tgt = y;
//program crashes for second test-case after reaching here
//i - the color of edge
//j - all the edges from x of color i
for (int i = 0; i < limt; ++i) {
for (int j = 0; j < edge[x][i].size(); ++j) {
ans += dfs(edge[x][i][j], i);
}
}
vist[x] = 0;
cout << ans << endl;
}
return 0;
}
The input i am giving is:
4 5
1 2 1
1 2 2
2 3 1
2 3 3
2 4 3
3
1 2
3 4
1 4
Here q is the number of test cases, the first case runs fine and gives the output 2 but on the second case program crashes with segmentation fault. I don't know what is the bug in it. I am sure i am not causing any overflow as the declarations are outside main().

In the second case, the dfs function causes infinite recursion.
The first call is dfs(u=2, c=1); which calls dfs(u=1, c=1); which calls dfs(u=2, c=1); and so on ad nauseum.
If you run your code in a debugger you should be able to see what happened by outputting the stack trace at the point of the segmentation fault.
Here is a picture of the graph generated by your data (where the colours are 1=red, 2=green, 3=blue):
Your loop inside main() starts at 3 and follows Red to find 2, then calls dfs(2, red); . (This was already a bit strange as you could have just called dfs(3, red) to get the same result). But then the dfs function just follows the first Red edge it finds so it ends up shuttling back and forth between 2 and 1.
To avoid this case you will need to add a way for dfs to know not to revisit a node it already visited. In fact you keep track of vist already but do not check it in the dfs function.
I think that just adding if ( vist[u] ) return 0; to the start of that function will fix this problem for this graph. However I think you should reset all of vist to 0 for each colour, not just for each testcase. For example in this graph if there were a blue edge from 2 to 4 but not from 3 to 4, the search would never find it because 2 was already marked visited during the red search.

Related

Generating an edge graph using four values a,b,c,d in c++

I'm having a trouble solving a question which asks me to generate an edge graph using 4 random numbers a,b,c,d , so the formula is as follows , to generate the nodges of the graph we'll use variable d , if we divide d with 3 and we get a remainder of 0 then 10 nodges are generated , if d/3 = 1 then 11 nodges if d/3 = 2 then 12 nodges are generated , as for the edges we have the following formula (i,j) ∈ U <-> ((ai+bj)/c) / d ≤ 1 , basically the edge will connect the nodge of i with the nodge of j if the formula after dividing by d gives a remainder smaller or equal to 1. Can someone tell me what's the problem with the code below ?
Here is the code :
#include <iostream>
#include <vector>
using namespace std;
struct Edge {
int src, dest;
};
class Graph
{
public:
vector<vector<int>> adjList;
Graph(vector<Edge> const& edges, int N)
{
adjList.resize(N);
for (auto& edge : edges)
{
adjList[edge.src].push_back(edge.dest);
}
}
};
void printGraph(Graph const& graph, int N)
{
for (int i = 0; i < N; i++)
{
cout << i << " ——> ";
for (int v : graph.adjList[i])
{
cout << v << " ";
}
cout << endl;
}
}
int main()
{
vector<Edge> edges;
int a, b, c, d,remainder,Nodges,result;
cout << "Enter 4 values : \n";
cin >> a >> b >> c >> d;
remainder = d % 3;
if (remainder == 0)
{
Nodges = 10;
}
else if (remainder == 1)
{
Nodges = 11;
}
else if (remainder == 2)
{
Nodges = 12;
}
for (int i = 0; i < Nodges; i++)
{
for (int j = 0; j < Nodges; j++)
{
result = ((a * i + b * j) / c) % d;
if (result <= 1)
{
edges =
{
{i,j}
};
}
}
}
Graph graph(edges, Nodges);
printGraph(graph, Nodges);
return 0;
}
At first you do not handle the case of d being outside of desired range. If d is e. g. 37, then you leave Nodges uninitialised, invoking undefined behaviour afterwards by reading it. You might add a final else to catch that case, printing some representation for an empty graph or a message and then return, so that you do not meet the for loops at all.
Simpler, though:
if(remainder < 3)
{
nodes = 10 + remainder;
// your for loops here
}
If you want to create an empty graph anyway, then don't forget to initialise nodes to 0; otherwise you should include the graph code in the if block above, too.
The main point your code fails is the following, though:
edges =
{
{i,j}
};
That way, you create a new vector again and again, always containing a single element, and the old one is replaced by that.
You actually need:
edges.emplace_back(i, j);
Finally: Get used to always check the stream's state after input operation. Users tend to provide invalid input, if you do not catch that you might get inexpected and actually undefined behaviour (such as dividing by 0).
if(std::cin >> a >> b >> c >> d)
{
/* your code */
}
else
{
// handle invalid input, e. g. by printing some message
// if you want to go on reading the stream:
// clears the error flags:
std::cin.clear();
// clears the stream's buffer yet containing the invalid input:
std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

Find how much xtreme distance two people walk together

Amir and Bond are walking on a street. Initially, both are at the position X=0 and they start walking in the direction of increasing X. After N seconds, they stop. Let's denote Amir's speed and Bond's speed during the i-th of these seconds by Ai and Bi respectively.
Sometimes, Aman and Bond walk together, i.e. with the same speed side by side. Let's define the xtreme distance as the total distance they walk this way. Find this xtreme distance.
Input
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N.
The second line contains N space-separated integers A1,A2,…,AN.
The third line contains N space-separated integers B1,B2,…,BN.
Output
For each test case, print a single line containing one integer ― the total weird distance. It can be proved that this distance is an integer.
Constraints
1≤T≤20
1≤N≤10e5
1≤Ai≤10e5 for each valid i
1≤Bi≤10e5 for each valid i
the sum of N over all test cases does not exceed 10e6
Code
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin >> T;
while(T--)
{
long long int N;
long long int i, w = 0;
cin >> N;
int * A = new int [N+1];
int * X = new int [N+1];
int * B = new int [N+1];
int * Y = new int [N+1];
Y[0] = 0;
X[0] = 0;
for(i=1;i<=N;i++)
{
cin >> A[i];
X[i] = X[i-1] + A[i];
}
for(i=1;i<=N;i++)
{
cin >> B[i];
Y[i] = Y[i-1] + B[i];
}
for(i=1;i<=N;i++)
{
if((X[i]-X[i-1]) == (Y[i]-Y[i-1]))
w += (Y[i] - Y[i-1]);
}
cout << w << endl;
delete [] A;
delete [] B;
delete [] X;
delete [] Y;
}
return 0;
}
Example Input
3
4
1 3 3 4
1 2 4 4
2
2 3
3 2
2
3 3
3 3
Example Output
5
0
6
Error
I am not able to figure out the error (may be there is error in constraints)

Painting rows and columns of a 2D matrix

Problem: We have given a nxm matrix, initially initialized with 0. We have to perform k queries:
Each query supports one of the two operations.
paint all elements in ri row with the colour ai .
paint all elements in ci column with the colour ai.
The same element can be painted more than once. But the color of that element is the same as the last painted colour for that element. You have to print the final matrix after painting.
Input: The first line contains three space-separated integers N,M,K
Next K lines consist of exactly one typep of operation to be performed
1) 1 ri ai means row ri is painted with color ai
2) 2 ci ai means column ci is painted with color ai
Output: Print the final matrix of size nxm after painting.
Sample Input: 3 3 3
1 1 3 2 2 1 1 2 2 Output: 3 1 3 2 2 2 0 1 0
I have written the following code to solve it but it is showing TLE for some test cases. Can you give me some idea how to solve it in efficient way?
My Code
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
int mat[5000][5000];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int n,m,k,q,r,c,val,i,j,re;
cin>>n>>m>>re;
while(re--)
{
cin>>q;
if(q==1)
{
cin>>r;
cin>>val;
i=r-1;
for(j=0,k=m-1;j<=k;j++,k--)
{
mat[i][j]=val;
mat[i][k]=val;
}
}
else if(q==2)
{
cin>>c>>val;
j=c-1;
for(i=0,k=n-1;i<=k;i++,k--)
{
mat[i][j]=val;
mat[k][j]=val;
}
}
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cout<<mat[i][j]<<" ";
}
cout<<endl;
}
}
It is only needed to memorize the last color that was affected to a given row or a given column, and the last time at which it was performed.
Then, for a given element mat[i][j], we simply have to check if the last modification on row i occured before of after the last modification on column j.
We don't even need to set such a matrix.
#include <iostream>
#include <ios>
#include <vector>
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(0);
int n, m, re;
std::cin >> n >> m >> re;
std::vector<int> row_color (n, 0), row_date (n, -1);
std::vector<int> col_color (m, 0), col_date (m, -1);
int date = 0;
while (re--) {
int q, index, val;
std::cin >> q >> index >> val;
index--;
if (q == 1) {
row_color[index] = val;
row_date[index] = date;
} else {
col_color[index] = val;
col_date[index] = date;
}
++date;
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int val = (row_date[i] > col_date[j]) ? row_color[i] : col_color[j];
std::cout << val << " ";
}
std::cout << "\n";
}
}
Instead of performing all the paint operations as they come in, you could:
While parsing the input, keep and update:
For each row the last color ai it is supposed to be painted in and the corresponding value k (running from 0 to K)
The same for each column
Setup an array of paint operations that combines both row and column paintings for all rows, columns where a painting occured
Sort the array based on k
Perform these operations on a matrix initialized with 0
This algorithm has an advantage if there is a large k (so, lots of overpainting) which you could expect from these kind of problems.

codechef: A puzzle game

problem statement:
Johnny has some difficulty memorizing the small prime numbers. So, his computer science teacher has asked him to play with the following puzzle game frequently.
The puzzle is a 3x3 board consisting of numbers from 1 to 9. The objective of the puzzle is to swap the tiles until the following final state is reached:
1 2 3
4 5 6
7 8 9
At each step, Johnny may swap two adjacent tiles if their sum is a prime number. Two tiles are considered adjacent if they have a common edge.
Help Johnny to find the shortest number of steps needed to reach the goal state.
My solution so far
#include<bits/stdc++.h>
using namespace std;
bool prime[20];
int matrix[3][3];
int solved[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9}
};
void display()
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cout<<matrix[row][col]<<" ";
}
cout<<endl;
}
cout<<endl<<endl;
}
bool check(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(matrix[i][j]!=solved[i][j])
return false;
}
}
return true;
}
int min(int a,int b)
{
return (a<b)?a:b;
}
void generate(){
memset(prime,true,sizeof(prime));
for(int i=2;i*i<20;i++){
if(prime[i]==true)
{
for(int j=2*i;j<20;j+=i)
prime[j]=false;
}
}
}
int getMoves(int row, int col){
if(row < 0 ||col< 0 || row>=3||col>=3){
return 0;
}
if(check()){
return 0;
}
int moves = 0;
for(int i = row-1 ; i<= row+1 ;i++)
{
for(int j = col -1 ; j<=col+1;j++)
{
if((i!=row-1&&j!=col-1)||(i!=row+1&&j!=col+1)||(i!=row+1&&j!=col-1)||(i!=row-1&&j!=col+1)){
if(prime[matrix[row][col]+matrix[i][j]]==true)
{
moves+=getMoves(i,j);
int temp;
temp = matrix[i][j];
matrix[i][j] = matrix[row][col];
matrix[row][col] = temp;
display();
}
}
}
}
return moves;
}
int Moves(){
int minMoves = INF;
for(int row = 0;row<3;row++)
{
for(int col = 0;col<3;col++)
{
int moves = getMoves(row,col);
minMoves = min(moves,minMoves);
}
}
return minMoves;
}
int main(){
generate();
int t;
cin>>t;
while(t--)
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cin>>matrix[row][col];
}
}
}
cout<<Moves();
}
sample testcase
Input:
2
7 3 2
4 1 5
6 8 9
9 8 5
2 4 1
3 7 6
Output:
6
-1
the program keeps crashing I guess because of memory overflow issue.
if (row < 0 || col< 0 || row >= 3 || row <= 3) {
return 0;
}
The code after this part is 'not accessible' because this condition is always true (... row >= 3 || row <= 3). You probably meant to write: (... row >= 3 || col >= 3)
I'm afraid your code is completely wrong and I don't think it could by fixed without complete rewrite. For example in function getMoves() your variables i and j can acquire value -1 so you will face access violation error. Secondly you have a recursion there, but you don't change data before you invoke recursion. Let's assume you want to swap 7 and 4. In the next step (because you didn't change input) you can swap 4 and 1. But it's not a correct move, because in that time, 4 should't be there. Thirdly your function getMoves() can end in an endless loop.
In conclusion, these kinds of problem are solved quite differently. You can for exmaple use backtracking algorithm or you can use A* algorithm. You will have to evaluate your current state. Let assume the following state:
7 3 2
4 5 6
1 8 9
You can measure number of moves that the number has to do to go to its correct position. So in this case 1 has to do 2 moves, 7 has to do 2 moves, 2 has to do 1 move as well as the number 3. The value of this state is 2 + 2 + 1 + 1 = 6. It's called an heuristic function. Now you can take this function and put it in an A* algorithm, and you should see the correct result.

Movie Weekend Codechef Beginner Section : Runtime Error

I have written the following code for the problem, ideone doesnt give me runtime error but the compiler for codechef is giving me one. The compiler in codechef is gcc 4.9.2
Problem [Link : https://www.codechef.com/problems/MOVIEWKN]
Little Egor is a huge movie fan. He likes watching different kinds of movies: from drama movies to comedy movies, from teen movies to horror movies. He is planning to visit cinema this weekend, but he's not sure which movie he should watch.
There are n movies to watch during this weekend. Each movie can be characterized by two integers Li and Ri, denoting the length and the rating of the corresponding movie. Egor wants to watch exactly one movie with the maximal value of Li × Ri. If there are several such movies, he would pick a one with the maximal Ri among them. If there is still a tie, he would pick the one with the minimal index among them.
Your task is to help Egor to pick a movie to watch during this weekend.
Expected Input
The first line of the input contains an integer T denoting the number of test cases.
The first line of the test case description contains an integer n(number of films).
The second line of the test case description contains n integers L1, L2, ...,Ln (L is the Length of the movie). The following line contains n integers R1, R2, ..., Rn(R is the Rating of the movie).
My Input
2
2
1 2
2 1
4
2 1 4 1
2 4 1 4
Expected Output
For each test case, output a single integer i denoting the index of the movie. Note that 1-based indexing is followed.
My Output
1
2
Explanation
In the first example case, both films have the same value of L × R, but the first film has a better rating.
In the second example case, the second and the fourth movies are equally good, but the second movie has a smaller index
My Solution
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
int T;
cin >> T;
cin.ignore();
if (T >= 1 && T <= 5) {
for (int q = 0; q < T; q++) {
int n;
size_t pos;
cin >> n;
cin.ignore();
if (n >= 1 && n <= 100) {
vector<int> L;
vector<int> R;
vector<int> C;
for (int u = 0; u < n; u++) {
int a;
cin >> a;
cin.ignore();
if (a >= 1 && a <= 100) {
L.push_back(a);
}
}
for (int u = 0; u < n; u++) {
int a;
cin >> a;
cin.ignore();
if (a >= 1 && a <= 100) {
R.push_back(a);
}
}
for (int u = 0; u < n; u++) {
int df = (L[u] * R[u]);
C.push_back(df);
}
for (size_t u = 0; u < C.size(); u++) {
int max = C[0];
if (max < C[u]) {
max = C[u];
pos = u+1;
}
if (max == C[u]) {
if (R[pos-1] < R[u]) { pos = u + 1; }
if (R[pos - 1] == R[u]) {
if (pos > u) { pos = u + 1; }
}
}
}
cout << pos << endl;
}
}
}
return 0;
}
After going through some of the questions on runtime error regarding codechef questions, i am guessing the problem is related to accessing an out of boundary element but i am not able to pinpoint the actual problem
In this line:
if (R[pos - 1] < R[u]) { pos = u + 1; }
The first time around the loop, pos is uninitialised, leading to undefined behaviour.
Simple fix:
add pos = 1 before the loop
I'm probably late but here is my simple solution:
t=int(input())
for j in range(0,t):
n=int(input())
a=[int(ele) for ele in input().split()]
b=[int(ele) for ele in input().split()]
c=[]
pos=0
max=-1
max2=-1
for i in range(0,n):
fl=0
c.append(a[i]*b[i])
if(max<c[i]):
max=c[i]
fl=1
if(fl==1):
pos=i+1
max2=b[i]
elif(max==c[i]):
if(max2<b[i]):
pos=i+1
max2=b[i]
print(pos)