Prims Algorithm : Runtime Error (C++) - c++

I was trying to implement the algorithm by myself, but I am getting a runtime error upon execution and i am quite unable to figure out why.
The code is split into three parts :
A) Storing the Graph in the form of an adjacency matrix, where a cell(i,j), if 0 represents no edge is present between the two vertices, where as non zero entry signifies the presence of an edge and the entry equals the weight of the edge from i to j.
B) Creating 3 arrays to hold weights, parents and to track the visited vertices, and in the First while loop of building the MST, I call the getMin function to provide me with the minimum weight amongst the non visited edges, then I update the weights of its corresponding neighbours if they are lower than their previously assigned weights, and continue this till the counter i becomes equal to n.
C)The last step is to print the MST which is quite straightforward.
Here is the code :
#include<iostream>
#include<climits>
using namespace std;
int getMin(int* weights, int n, bool* visited) {
int minimum = INT_MAX;
int minIndex = -1;
for(int i = 0; i < n; i++) {
if(weights[i] < minimum && !visited[i]) {
minimum = weights[i];
minIndex = i;
}
}
return minIndex;
}
int main() {
int n, e;
cin >> n >> e;
//Creating an adjacency matrix to store Graph
int** edges = new int*[n];
for(int i = 0; i < n; i++) {
edges[i] = new int[n];
for(int j = 0; j < n; j++) {
//Initializing each entry as 0(False) for now
edges[i][j] = 0;
}
}
//Taking input of edges
for(int i = 0; i < e; i++) {
int f,s,w;
cin >> f >> s >> w;
edges[f][s] = edges[s][f] = w; //Storing weights as the entries
}
//Array 1 for tracking the visited vertices
bool* visited = new bool[n];
for(int i = 0; i < n; i++) {
visited[i] = false;
}
//Array 2 for maintaining weights
int* weights = new int[n];
for(int i = 0; i < n; i++) {
if(i == 0) {
//Treating 0 as source vertex
weights[i] = 0;
}
else {
weights[i] = INT_MAX;
}
}
//Array 3 for maintaining parents of each vertex
//Will be helpful in tracing the MST after n - 1 edges are added
int* parent = new int[n];
for(int i = 0; i < n; i++) {
if(i == 0) {
//Source vertex has no parent
parent[i] = -1;
}
else {
//INT_MIN symbolizing no parents yet
parent[i] = INT_MIN;
}
}
//Building the MST
int i = 0;
while(i < n) {
int minimum = getMin(weights, n, visited);
visited[minimum] = true;
for(int j = 0; j < n; j++) {
if(edges[minimum][j] != 0 && !visited[j]) {
if(edges[minimum][j] < weights[j]) {
weights[j] = edges[minimum][j];
parent[j] = minimum;
}
}
}
i++;
}
//Printing the MST
int k = 0;
while(k < n) {
for(int j = 0; j < n; j++) {
if(parent[j] == k) {
cout << k << " " << j << " " << edges[i][j] << endl;
}
}
k++;
}
return 0;
}

Related

Given an undirected graph G(V,E), find and print all the connected components of the given graph G

This is the question I am trying to code. I have written the following code but I don't know how can I store the elements in the vector in getComponent() function and retrieve it inside main function.
I have used ans as a vector variable. I am passing its address so that I do not have to return anything. But I am getting compilation error while running the code.
#include<vector>
#include <bits/stdc++.h>
using namespace std;
void getComponent(int **edges, int n, int sv, int * visited, vector<int>*ans){
visited[sv] = 1;
ans->push_back(sv);
for(int i = 0; i < n; i++){
if(i == sv)continue;
if(edges[sv][i] == 1){
if(visited[i] == 0)
getComponent(edges, n, i, visited, ans);
}
}
}
int main() {
// Write your code here
int n, e;
cin>>n>>e;
int **edges = new int *[n];
for(int i = 0; i < n; i++){
edges[i] = new int[n];
for(int j = 0; j < n; j++){
edges[i][j] = 0;
}
}
for(int i = 0; i <e; i++){
int a, b;
cin>>a>>b;
edges[a][b] = 1;
edges[b][a] = 1;
}
int *visited = new int[n];
for(int i = 0; i < n; i++)
visited[i] = 0;
for(int i = 0; i < n; i++){
if(visited[i] == 0){
vector<int>*ans;
getComponent(edges, n, i, visited, ans);
for (auto x : ans)
cout << x << " ";
cout<<endl;
}
}
}
You need to actually create an ans vector and pass it's address:
for(int i = 0; i < n; i++){
if(visited[i] == 0){
vector<int> ans;
getComponent(edges, n, i, visited, &ans);
for (auto x : ans)
cout << x << " ";
cout<<endl;
}
}
After that you should replace all C-style arrays with std::vector and pass references instead of pointers.

Water the plants (competitive programming)

I was trying to solve this proble:
A gallery with plants is divided into n parts, numbered : 0,1,2,3...n-1. There are provisions for attaching water sprinklers at every partition. A sprinkler with range x at partition i can water all partitions from i-x to i+x.
Given an array gallery[ ] consisting of n integers, where gallery[i] is the range of sprinkler at partition i (power==-1 indicates no sprinkler attached), return the minimum number of sprinklers that need to be turned on to water the complete gallery.
If there is no possible way to water the full length using the given sprinklers, print -1.
and this is how I ended up trying-
Create a frequency array such that the ith element contains the number of sprinklers that are watering the ith part of the gallery.
If any element of this array is zero after going through all the sprinklers, then return -1 as even if all the sprinklers tried they couldn't water each part.
Then, std::stable_sort all the sprinklers based on their range, in increasing order.
Then, remove a sprinkler if it is redundant, starting from the smallest range to the largest.
My implementation of the same-
typedef struct sprinkler {
int l;
int r;
} sprinkler;
int min_sprinklers(int gallery[], int n)
{
int freq[n];
vector<sprinkler> vec;
for(int i = 0; i < n; i++) freq[i] = 0;
for(int i = 0 ; i < n; i++) {
int x = gallery[i];
if(x == -1) continue;
int l = max(0, i - x);
int r = min(n-1, i + x);
sprinkler s;
s.l = l;
s.r = r;
vec.push_back(s);
for(int j = l; j <= r; j++) {
freq[j]++;
}
}
for(int i = 0; i < n; i++) {
if(freq[i] == 0) return -1;
}
stable_sort(vec.begin(), vec.end(), [](sprinkler s1, sprinkler s2) { return s1.r-s1.l < s2.r-s2.l; });
int sprinklers = vec.size();
for(int i = 0; i < vec.size(); i++) {
int l = vec[i].l;
int r = vec[i].r;
bool flag = false;
for(int j = l; j <= r; j++) {
if(freq[j] == 1) {
flag = true;
break;
}
}
if(!flag) {
for(int j = l; j <= r; j++) freq[j]--;
sprinklers--;
}
}
return sprinklers;
}
But I still seem to be missing something and still don't know what.
Link to try my code:
https://practice.geeksforgeeks.org/problems/410d51d667ab93f2219b15126f001f32e8bb029e/0/?category[]=Greedy&category[]=Greedy&difficulty[]=1&page=1&query=category[]Greedydifficulty[]1page1category[]Greedy#

How do I find the number with the most divisors in an array?

I have to input numbers into an array and at the end get the number that has the most divisors, or if there are more numbers with the same amount, print out the first one.
Example: 4 numbers, 6 12 48 108. 108 has the most divisors, so this one needs to show up. if there were numbers after 108 with the same amount of divisors, 108 would have still been the only one to show up.
#include <iostream>
using namespace std;
int main()
{
int n = 0, d, largestCnt = 0;
int cntA=0, cntB=0;
cout << "How many elements?\n";
cin >> n;
int* v = new int[n];
for(int i=0; i<n; i++)
cin >> v[i];
for(int i=0; i<n; i++){
for(d=2; d<v[i]/2; d++)
if(v[i]%d==0)
cntA++;
for(d=2; d<v[i+1]/2; d++)
if(v[i+1]%d==0)
cntB++;
if(cntA > largestCnt)
largestCnt = cntA;
if(cntB > largestCnt)
largestCnt = cntB;
}
cout << largestCnt;
return 0;
}
this is the most I've done the past 2 hours, and I can't get past it
EDIT:
#include <iostream>
using namespace std;
int main()
{
int n = 0, d;
int mostDivisors=0, number_with_most_divisors=0;
int currentDivisors = 0;
cout << "How many elements?\n";
cin >> n;
int* v = new int[n];
for(int i=0; i<n; i++)
cin >> v[i];
number_with_most_divisors = v[0];
for(d=2; d<=v[0]/2; d++){
if(v[0]%d == 0)
mostDivisors++;
}
for(int i=1; i<n; i++){
for(d=2; d<=v[i]/2; d++)
if(v[i]%d == 0)
currentDivisors++;
if(currentDivisors > mostDivisors){
mostDivisors = currentDivisors;
number_with_most_divisors = v[i];
}
}
cout << number_with_most_divisors;
return 0;
}
Here is the algorithm of what you have to do:
Count the number of divisors of the first element in array. Save this value in mostDivisors. Set number_with_most_divisors as the first element in the array.
Start from the second element in array (position 1) and for each element, count how many divisors it has, save it in currentDivisors. If currentDivisors > mostDivisors then set mostDivisors to be equal to currentDivisors and update number_with_most_divisors to be the current element in the array.
The result is number_with_most_divisors at the end of the loop.
UPDATE
You are forgetting to initialize currentDivisors for each element after the first loop:
for(int i=1; i<n; i++){
currentDivisors = 0; // You forgot to put this line!
for(d=2; d<=v[i]/2; d++)
if(v[i]%d == 0)
currentDivisors++;
if(currentDivisors > mostDivisors){
mostDivisors = currentDivisors;
number_with_most_divisors = v[i];
}
// function to count the divisors
int countDivisors(int n)
{
int cnt = 0;
for (int i = 1; i <= sqrt(n); i++) {
if (n % i == 0) {
// If divisors are equal,
// count only one
if (n / i == i)
cnt++;
else // Otherwise count both
cnt = cnt + 2;
}
}
return cnt;
}
You can loop to enter the numbers into an array
#include <iostream>
int main() {
int n = 0, max_divs = 0, count = 0, max_divs_index = 0;
std::cin >> n;
int *v = new int[n];
for (int i = 0; i < n; ++i) std::cin >> v[i];
for (int i = 0; i < n; ++i) {
count = 0; // resetting count to 0 in each iteration
for (int j = 2; j < v[i]/2; ++j)
if (v[i] % j == 0) count++; // checking if the number is divisible by numbers between 1 and number itself/2 (1 and num/2 exclusive)
if (count > max_divs) { // checking if current count is greater than the maximum divisors
max_divs = count; // updating maximum divisors
max_divs_index = i; // updating the index of array element with maximum divisors
}
}
std::cout << v[max_divs_index];
delete[] v;
return 0;
}

Selection Sort in c++

i'm trying to understand selection sort from this video:
https://www.youtube.com/watch?v=79AB11J5BqU
this is my current code :
#include <iostream>
int main() {
int numbers[5]={5,3,4,1,2};
int temp;
std::cout<<"BEFORE SORT : \n";
for(int x=0;x<5;x++){
std::cout<<numbers[x]<<" ";
}
for (int i = 0; i < 5; ++i) {
for (int j = i+1; j < 5; ++j) {
if(numbers[j]<numbers[i]){
temp = numbers[j];
numbers[j] = numbers[i];
numbers[i] = temp;
}
}
}
std::cout<<"\n\nAFTER SORT : \n";
for(int x=0;x<5;x++){
std::cout<<numbers[x]<<" ";
}
}
Am i doing the selection sort just like the video?
or am i instead doing buble sort ?
Thanks
In selection sort you find a minimal (or maximal) element and put it to top (bottom), then repeat it again for the rest of list.
It would be a selection sort, but you don't need to do swap every number you compare to find the smallest one. Store smallest number index in each internal loop and do one swap at the end of it.
unsigned minIndex;
for (int i = 0; i < 5; ++i) {
minIndex = i;
for (int j = i + 1; j < 5; ++j) {
if(numbers[j] < numbers[minIndex]){
minIndex = j;
}
}
if (minIndex != i) { // Do swapping
temp = numbers[i];
numbers[i] = numbers[minIndex];
numbers[minIndex] = temp;
}
}
The selection sort algorithm sorts an array by repeatedly finding the minimum element (considering ascending order) from unsorted part and putting it at the beginning.
#include<iostream>
using namespace std;
// Selection Sort//
void Selection_Sort(int a[],int n)
{
for(int i=0;i<n-1;i++)
{
int min_index=i;
for(int j=i;j<n-1;j++)
{
if(a[j]<a[min_index]){
min_index=j;
}
}
swap(a[i],a[min_index]);
}
}
int main()
{
int n,key;
cin>>n;
int a[1000];
for(int i=0;i<n;i++)
{
cin>>a[i];
}
Selection_Sort(a,n);
for(int i=0;i<n;i++)
{
cout<<a[i];
}
}

Kosaraju's Algorithm for spoj's BOTTOM

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:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <fstream>
#include <iterator>
#include <queue>
using namespace std;
int k = 0;
int V, E;
bool fix[5001];
bool fix2[5001];
int compNum[5001];
void dfs(int v, vector< vector<int> >&G, bool *fix, vector <int> &out) {
fix[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix[u]) {
fix[u] = true;
dfs(u, G, fix, out);
}
}
out.push_back(v);
}
void dfs2(int v, vector< vector<int> >&G, bool *fix2, vector < vector<int> > &components) {
fix2[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix2[u]) {
fix2[u] = true;
dfs2(u, G, fix2, components);
}
}
components[k].push_back(v);
compNum[v] = k;
}
int main() {
int a, b;
while (true) {
cin >> V; if (V == 0) break; cin >> E;
vector< vector<int> >G(V + 1);
vector< vector<int> >G2(V + 1);
vector<int>out;
vector < vector<int> >components(V + 1);
for (int i = 0; i < E; i++) {
cin >> a >> b;
G[a].push_back(b);
G2[b].push_back(a);
}
for (int i = 1; i <= V; i++) {
if (!fix[i])
dfs(i, G, fix, out);
}
reverse(out.begin(), out.end());
for (int i = 0; i < out.size(); i++){
if (!fix2[out[i]]) {
dfs2(out[i], G2, fix2, components);
k++;
}
}
vector<int>gamotana;
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
bool check = true;
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
check = false; goto next123;
}
}
if (check)
gamotana.push_back(components[i][j]);
}
next123:;
}
sort(gamotana.begin(), gamotana.end());
for (int i = 0; i < gamotana.size(); i++)
cout << gamotana[i] << " ";
for (int i = 0; i < 5001; i++) {
fix[i] = false;
fix2[i] = false;
compNum[i] = -1;
}
k = 0;
cout << endl;
}
return 0;
}
In your algorithm description you say you eliminate the entire connected component if some edge leads to a different component.
However, in your code you appear to add all vertices j in component i to your solution until you find an edge leading out. In other words, even if a component is not a sink you may still incorrectly report some of the vertices as being sinks.
I imagine you should do something more like this:
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
goto next123;
}
}
}
for (int j = 0; j < components[i].size(); j++)
gamotana.push_back(components[i][j]);
next123:;
}
Of course, there may be more issues. I would recommend you try constructing and testing some small examples first, and perhaps testing against a brute force solver to identify failing cases.
#include<bits/stdc++.h>
using namespace std;
void dfs(vector<int>* edges, stack<int>& finishedVertices, bool* visited, int n, int start){
visited[start] = true;
for(int i = 0 ; i < edges[start].size() ; i++){
int node = edges[start][i];
if(!visited[node]){
dfs(edges, finishedVertices, visited, n, node);
}
}
finishedVertices.push(start);
}
void dfs_reverse(vector<int>* edgesT, bool* visited, unordered_map<int,vector<int>>& SCC, int node, int k){
SCC[k].push_back(node);
visited[node] = true;
for(int i = 0 ; i < edgesT[node].size() ; i++){
int new_node = edgesT[node][i];
if(!visited[new_node]){
dfs_reverse(edgesT, visited, SCC, new_node, k);
}
}
}
void getSCC(vector<int>* edges, vector<int>* edgesT, int n){
bool* visited = new bool[n];
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
stack<int> finishedVertices;
for(int i = 0 ; i < n ; i++){
if(!visited[i]){
dfs(edges, finishedVertices, visited, n, i);
}
}
unordered_map<int,vector<int>> SCC;
int k = 0;
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
while(!finishedVertices.empty()){
int node = finishedVertices.top();
finishedVertices.pop();
if(!visited[node]){
dfs_reverse(edgesT, visited, SCC, node, k);
k++;
}
}
int flag = 1;
vector<int> ans;
vector<int> bottom;
for(int i = 0 ; i < k ; i++){
for(int j = 0 ; j < SCC[i].size(); j++){
ans.push_back(SCC[i][j]);
}
for(int m = 0 ; m < ans.size() ; m++){
int node = ans[m];
for(int j = 0 ; j < edges[node].size() ; j++){
int new_node = edges[node][j];
vector<int> :: iterator it;
it = find(ans.begin(), ans.end(), new_node);
if(it == ans.end()){
flag = 0;
break;
}
}
if(flag == 0)
break;
}
if(flag == 1){
for(int j = 0 ; j < ans.size() ; j++)
bottom.push_back(ans[j]);
}
flag = 1;
ans.clear();
}
sort(bottom.begin(), bottom.end());
for(int i = 0 ; i < bottom.size() ; i++)
cout << bottom[i] + 1 << " ";
cout << endl;
}
int main(){
while(true){
int n;
cin >> n;
if(n == 0)
break;
vector<int>* edges = new vector<int>[n];
vector<int>* edgesT = new vector<int>[n];
int e;
cin >> e;
for(int i = 0 ; i < e ; i++){
int x, y;
cin >> x >> y;
edges[x-1].push_back(y-1);
edgesT[y-1].push_back(x-1);
}
getSCC(edges, edgesT, n);
delete [] edges;
delete [] edgesT;
}
return 0;
}