Kruskal algorithm, cycles and unvisited vertices - c++

Algorithm does not pass through vertex 1(Z) and 4(B). Cycles are for vertices 12-13-14(S-T-K) and 13-15-16(T-L-R), how to fix it?
Below is the command, my code, graph, my output and the input file.
The input file contains the data of one connected graph. Its first line contains an integer Nv that specifies the number of edges of the graph. Then there are Nv lines containing descriptions of the consecutive vertices. The description of each node contains a positive integer corresponding to its identifier and a text string corresponding to its name. It can be assumed that both the number of vertices and the identifiers will not exceed 32,767, the length of the name will not be more than 8 characters, and it will only contain letters or numbers. The next line is the number Ne that specifies the number of edges in the graph. Then there are Ne lines containing the description of the subsequent edges. The description of each edge contains three positive integers, the first two correspond to the identifiers of the vertices connected by the given edge, the third is the weight of this edge.
The output should be exactly as many lines as the edges contain the Minimal Spanning Tree, each line should contain information about one edge. The information for each edge should contain the names of the vertices and the edge weight separated by spaces.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Vertex
{
int id;
char name[8];
};
struct Edges
{
int source;
int destination;
int weight;
};
void quickSort(Edges* tab, int left, int right)
{
if (right <= left)
{
return;
}
int i = left - 1, j = right + 1, pivot = tab[(left + right) / 2].weight;
while (1)
{
while (pivot > tab[++i].weight);
while (pivot < tab[--j].weight);
if (i <= j)
{
swap(tab[i].source, tab[j].source);
swap(tab[i].destination, tab[j].destination);
swap(tab[i].weight, tab[j].weight);
}
else
{
break;
}
}
if (j > left)
{
quickSort(tab, left, j);
}
if (i < right)
{
quickSort(tab, i, right);
}
}
int main()
{
int vertexnumber;
int edgenumber;
Edges* edgeList{};
vector<Edges> MST;
vector<Vertex> vertexList;
cin >> vertexnumber;
for (int i = 0; i < vertexnumber; i++)
{
vertexList.push_back(Vertex());
cin >> vertexList[i].id;
cin >> vertexList[i].name;
}
cin >> edgenumber;
edgeList = new Edges[edgenumber];
for (int i = 0; i < edgenumber; i++)
{
cin >> edgeList[i].source;
cin >> edgeList[i].destination;
cin >> edgeList[i].weight;
}
quickSort(edgeList, 0, edgenumber);
int iterator = 0;
for (int i = 0; i < edgenumber; i++)
{
bool isLoop = false;
int helper = edgeList[i].source;
for (int j = 0; j < MST.size(); j++)
{
for (int k = 0; k < MST.size(); k++)
{
if (MST[k].source == helper)
{
helper = MST[k].destination;
break;
}
if (MST[k].destination == helper)
{
helper = MST[k].source;
break;
}
}
if (edgeList[i].destination == helper)
{
isLoop = true;
break;
}
}
if (!isLoop)
{
MST.push_back(Edges());
MST[iterator].destination = edgeList[i].destination;
MST[iterator].source = edgeList[i].source;
MST[iterator].weight = edgeList[i].weight;
iterator++;
if (MST.size() >= vertexnumber - 1)
{
break;
}
}
}
for (int i = 0; i < MST.size(); i++)
{
for (int j = 0; j < vertexList.size(); j++)
{
if (vertexList[j].id == MST[i].source)
{
cout << vertexList[j].name << " ";
break;
}
}
for (int j = 0; j < vertexList.size(); j++)
{
if (vertexList[j].id == MST[i].destination)
{
cout << vertexList[j].name << " ";
break;
}
}
cout << MST[i].weight << endl;
}
}
S K 60
D O 82
O S 96
F P 108
T K 109
P C 110
W E 115
S T 124
E T 130
G N 135
T R 136
L R 138
F D 139
T L 142
G C 145
16
1 Z
2 G
3 N
4 B
5 F
6 P
7 C
8 W
9 E
10 D
11 O
12 S
13 T
14 K
15 L
16 R
34
1 2 288
1 5 175
1 6 192
2 3 135
2 6 246
2 7 145
3 4 188
3 7 177
3 8 174
4 8 179
4 15 213
5 6 108
5 10 139
6 7 110
6 9 187
6 10 147
6 11 203
7 8 218
7 9 172
8 9 115
8 13 146
8 15 153
9 11 168
9 12 174
9 13 130
10 11 82
11 12 96
12 13 124
12 14 60
13 14 109
13 15 142
13 16 136
14 16 148
15 16 138

There are at least two issues with your code:
When you call your quicksort implementation you should start it with edgenumber - 1 as right border index, otherwise you access uninitialised data.
Your loop detection is not correct because you don't care for the case where there are already three or more edges in MST with the same vertex. Here the path can split but you just follow one of them. Thus you add also cyclic edges to MST and the limit of MST.size() >= vertexnumber - 1 is reached before you could link all vertices to the tree.
I hope this helps. There are plenty of implementations in the net (e.g. see external links in the wikipedia article) where you can study how others have solved the task of loop detection. But if my assumption is right that you are doing this as homework, of course, it is better to try yourself.

Related

how to build a two three series program in C++

i have this CS question that says:
We will define a series two three to be a series whose first term is some natural number. If the value of the member number n in the series is x, then the value of the (n +1)th member in the series is: (x % 2 ==0) ? x/2 : x*3 +1.
You must write a program that prints two or three series starting with the numbers 1 to twenty-five (not inclusive), but the creation of each series will stop when a value greater than a thousand or a value that has already appeared in a previous series is produced (and therefore the sub-series that was produced from this array onwards has already been produced). The value that is produced must be displayed again, thus stopping the production of the series.
now the code i have written outputs a similar result to the solution output but it needs some changes in order to get the same exact result which i couldn't figure out, this is my code.
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
int array[25];
for (int i = 1; i < 25; i++)
{
int currentNum = i;
int theNumAfter;
bool occured = false;
while (occured == false)
{
for (int i = 0; i <= 25; i++)
{
if (array[i] == currentNum)
{
occured = true;
cout << endl;
}
}
array[currentNum] = currentNum;
cout << currentNum << " ";
if (currentNum % 2 == 0)
{
theNumAfter = currentNum / 2;
}
else
{
theNumAfter = (3 * currentNum) + 1;
}
array[theNumAfter] = theNumAfter;
cout << theNumAfter << " ";
currentNum = theNumAfter;
}
}
}
the code doesn't take any input and there is only one right output which should be this:
1 4 2 1
2
3 10 5 16 8 4
4
5
6 3
7 22 11 34 17 52 26 13 40 20 10
8
9 28 14 7
10
11
12 6
13
14
15 46 23 70 35 106 53 160 80 40
16
17
18 9
19 58 29 88 44 22
20
21 64 32 16
22
23
24 12
the result of my code:
1 4
4 2
2 1 3 10
10 5
4 2
5 16 6 3
3 10 7 22
22 11 8 4
4 2 9 28 28 14
14 7
10 5
11 34 12 6
6 3 13 40 40 20
20 10
14 7 15 46 46 23
23 70
16 8 17 52 52 26 26 13
13 40 18 9
9 28 19 58 58 29 29 88 88 44 44 22
22 11
what should i change in the code, so we have matching outputs. thanks in advance
the creation of each series will stop when a value greater than a thousand or a value that has already appeared in a previous series is produced.
Up to 24, none of the produced values is greater than a thousand, but the posted code still has an access out of bounds bug:
int main()
{
int array[25];
// ^^
for (int i = 1; i < 25; i++)
{
int currentNum = i;
int theNumAfter;
// ...
array[currentNum] = currentNum;
// ...
array[theNumAfter] = theNumAfter;
// ...
}
// ...
}
Note the many of numbers in the expected output are greater than 25.
I'm not sure what this part was supposed to achive:
for (int i = 0; i <= 25; i++)
{ // ^^^^^^^ it "checks" only the first 25 values that may occur
if (array[i] == currentNum)
{
occured = true;
cout << endl; // <-- The duplicate should be printed before the newline.
// Here it should break out of the loop.
}
}
array[currentNum] = currentNum;
cout << currentNum << " ";
But it fails to produce the expected output.
I'd use a simple array of 1000 bools to memorize the already occurred numbers.
#include <iostream>
int main()
{
constexpr int limit{ 1'000 };
bool already_seen[limit + 1]{};
for (int i = 1; i < 25; i++)
{
int current{ i };
while ( current <= limit and not already_seen[current] )
{
std::cout << current << ' ';
already_seen[current] = true;
if ( current % 2 == 0)
{
current /= 2;
}
else
{
current = (3 * current) + 1;
}
}
std::cout << current << '\n';
}
}
Testable here.

Matrix Enumeration Lab

Your job is to write a program called matrix_enum, which takes three command line arguments: W, E and either an 'x' or an 'h'. Your program will enumerate all of the matrices for W and E, in any order you want, and print them out in one of the following two formats:
If the last argument is 'x', then you'll print the matrices out in the format below. You should print each matrix as W lines of W characters that are '.', 'X' or 'E'. After each matrix, you print a blank line.
If the last argument is 'h', then you'll convert each line of each matrix into an integer, and print that integer in hexadecimal, with no leading 0's and no leading "0x". If element i in a row is 'X' or 'E', then you'll set the i-th bit of the number to 1. Otherwise, the i-th bit is zero. You'll print each integer on its own line, and print a blank line at the end of each matrix.
UNIX> matrix_enum 2 0 x
X.
.X
.X
X.
UNIX> matrix_enum 2 0 h
1
2
2
1
Here's my code so far but I don't know where to go from here
5 class Matrix {
6 public:
7 int W;
8 int E;
9 int P; /* This is 'x' or 'h' */
10 vector <int> Perm; /* Permutation of 0 .. (W-1), for the 'X' elements. */
11 vector <int> Non_X; /* This is the row/col id of each of the non-X elements. */
12 vector <int> E_ID; /* This is the row/col id of the E elements */
13 void Print(); /* Print the matrix defined by W, Perm and E_ID */
14 void Permute(int index); /* This is the recursive permuting method. */
15 void Choose(int index); /* This is the recursive n-choose-k method. */
16 };
17
18 void Matrix::Print() {
19
20 for(int i = 0; i < Perm.size(); i++) {
21
22
23 }
24 }
25
26 void Matrix::Permute(int index) {
27 //recursion to permute matrix
28 string tmp;
29
30 if(index == Perm.size()) {
31 //Base case
32 for (int i = 0; i < W; i++) {
33 for(int j = 0; j < W; j++) {
34 //check if there is an 'x'
35 if(Perm.at(i) == j) {
36 continue;
37 }
38
39 Non_X.push_back(Perm.at(i));
40 Choose(0);
41 return;
42 }
43 }
44 }
45 //swap Perm[index] with Perm[i] and swap back
46 for(int i = index; i < Perm.size(); i++) {
47 //swap
48 tmp = Perm[i];
49 Perm[i] = Perm[index];
50 Perm[index] = tmp;
51
52 Permute(index+1);
53
54 //backtrack
55 tmp = Perm[i];
56 Perm[i] = Perm[index];
57 Perm[index] = tmp;
58 }
59 }
60
61 void Matrix::Choose(int index) {
62 //n choose k permutation
63 //people = non x
64 //eid = teams
65 if (E - E_ID.size() == 0) {
66 cout << E_ID[0];
67 for (i = 1; i < E_ID.size(); i++) cout << " " << E_ID[i];
68 cout << endl;
69 return;
70 }
71
72 if ((E - E_ID.size()) > Non_X.size() - index) return;
73
74 E_ID.push_back(Non_X[index]);
75 Choose(index+1, (E - E_ID.size())-1);
76 E_ID.pop_back();
77
78 Choose(index+1, (E - E_ID.size()));
79
80 // call Print();
81 }

So I made a program that prints Pascal's Triangle in C++ & Java and for some reason it starts breaking when I make 14+ rows?

#include <iostream>
long factorial(long n)
{
int x = 1;
for(int i = 2; i <= n; i++) x = x * i;
return x;
}
long nCr(long n, long r)
{
return factorial(n) / (factorial(r) * factorial(n - r));
}
int main()
{
int row;
std::cout << "Enter the number of rows: ";
std::cin >> row;
for (int n = 1; n <= row; n++)
{
for (int s = 1; s <= row - n; s++) std::cout << " "; //space
for (int r = 0; r != n; r++) std::cout << nCr(n-1, r) << " "; //numbers
std::cout << std::endl;
}
}
The code works perfectly fine when constructing a 13-row Pascal's Triangle(albeit a bit ugly), but for some reason it starts becoming inaccurate/wrong at the 14th row and prints this:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 4 24 88 221 399 532 532 399 221 88 24 4 1
The purpose of Pascals Triangle is to avoid the calculation of big factorials. See, how many multiplactions you need to make. And by calculating the combinations, n choose k, you quickly come to situations, where build in datatypes overflow.
To tackle such problems, Pascals Triangle is the ideal solution. You can survive, by just summing up values. Row by row.
There are really many solutions for that. I show an example using 2 std::vectors. One holds the current row (the upper row) and the other the next row. For the next row, we can just add the values from the upper row. That is really simple.
Please see:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <iomanip>
using ull = unsigned long long;
constexpr size_t NumberOfRows = 50U;
int main() {
std::vector<ull> current{ 1 };
std::vector<ull> next{};
current.reserve(NumberOfRows+2);next.reserve(NumberOfRows+3);
for (size_t i{}; i < NumberOfRows; ++i) {
// Next row has one element more
next.resize(current.size() + 1);
// Each row starts and ends with a 1
next.front() = 1; next.back() = 1;
// For the next row, sum up the upper to values from the current row
for (unsigned k{ 1 }; k < next.size() - 1; ++k)
next[k] = current[k - 1] + current[k];
// Debug Output
std::cout << std::setw(NumberOfRows - i + 2) << "";
std::copy(current.begin(), current.end(), std::ostream_iterator<ull>(std::cout, " "));
std::cout << '\n';
// Prepare next loop run. Assign the calculated row to current
current = std::move(next);
}
return 0;
}
When you calculate factorial(n) you are overflowing LONG_MAX. By doing an unsigned long you get more positive integers but this will only push the maximum rows a few more. If you know that your doing factorial division you can remove a lot of the large numbers by changing the logic.
ie: 13! /11! = (13 * 12 * 11 * 10 * 9....) / (11 * 10 * 9...)
can be simplified to (13* 12) which will remove the overflow

Dynamic programming problem -Minimum Cost Path

I was trying this problem - Minimum Cost Path.
I have solved the problem using Dijkstra's Shortest Path Algorithm. But when i tried this using recursion+memoisation i.e. using dynamic programming, i got stuck and could not debug my code. I need help as to where my code is wrong!!
I am really glad for the help.
#include<bits/stdc++.h>
using namespace std;
int n;
int a[105][105], dp[105][105];
int dfs(int x, int y){
if(x < 0 || y < 0 || x >= n || y >= n){
return INT_MAX;
}
if(x == 0 && y== 0){
return a[0][0];
}
if(dp[x][y] != -1){
return dp[x][y];
}
dp[x][y] = a[x][y] + min(dfs(x-1, y), min(dfs(x, y-1), min(dfs(x+1, y), dfs(x, y+1))));
return dp[x][y];
}
int main(){
int tt;
cin >> tt;
while(tt--){
int n;
cin >> n;
for(int i = 0 ; i < n; i++){
for(int j = 0; j < n; j++){
cin >> a[i][j];
dp[i][j] = -1;
}
}
cout << dfs(n-1, n-1) << endl;
}
return 0;
}
Example:
Input:
2
5
31 100 65 12 18 10 13 47 157 6 100 113 174 11 33 88 124 41 20 140 99 32 111 41 20
2
42 93 7 14
Output:
327
63
I am getting 2147483647 as the output for both the cases, which is the value of INT_MAX.
The global variable n that dfs looks at is always zero (by static initialization), it's never assigned a value. When main calls, say, dfs(4, 4), the function immediately returns INT_MAX due to 4 >= 0 check.
Once you fix this simple issue, you'll discover that your program crashes due to stack overflow. You see, dfs(4, 4) calls dfs(3, 4), which in turn calls dfs(4, 4), which calls dfs(3, 4), which ...
This is not really a dynamic programming problem. It's a "shortest path in a graph" problem, suitable for, say, Dijkstra or A* algorithms.

Logical Error in given program cannot find it

In this problem we are given two arrays attackArray and defArray both of size N.
Now we think each array element to be a say, solider.
We need to output the particular element which is greater than its neighbours & greater than their sum. If multiple elements can the output then output the largest one.
-1 If no such element is found.
Custom input I tried to run it with
Input
4
4
1 1 4 1
3 4 2 1
7
5 4 5 4 5 4 5
3 2 4 7 2 5 9
3
5 8 1
5 6 20
20
46 35 17 37 39 48 10 49 44 11 36 4 2 22 16 41 26 8 15 40
4 41 6 35 49 50 28 46 22 17 13 36 31 2 33 14 150 47 29 39
Output
3
-1
20
-1
.Last output should've been 150.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin >> T;
if (T > 100 || T < 1)
return 0;
do {
vector<int> ans;
int N;
cin >> N;
if (N > 100 || N < 3)
return 0;
vector<long long int> attackArray(N), defArray(N);
for (int i = 0; i < N; i++) {
cin >> attackArray.at(i);
}
for (int i = 0; i < N; i++) {
cin >> defArray.at(i);
}
if (defArray.at(0) > attackArray.at(1) && defArray.at(0) > attackArray.at(N - 1) && defArray.at(0) > attackArray.at(1) + attackArray.at(N - 1)) {
ans.push_back(defArray.at(0));
}
if (defArray.at(N - 1) > attackArray.at(0) && defArray.at(N - 1) > attackArray.at(N - 2) && defArray.at(N - 1) > attackArray.at(0) + attackArray.at(N - 2)) {
ans.push_back(defArray.at(N - 1));
}
for (int i = 1; i < N - 1; i++) {
int nexti, previ;
nexti = i + 1;
previ = i - 1;
if (defArray.at(i) > attackArray.at(nexti) && defArray.at(i) > attackArray.at(previ) && defArray.at(i) > attackArray.at(nexti) + attackArray.at(previ)) {
ans.push_back(defArray.at(i));
}
else {
ans.push_back(-1);
break;
}
}
sort(ans.begin(), ans.end(), greater<int>());
cout << ans[0] << endl;
T--;
} while (T != 0);
return 0;
}
It works for the first line because the first element in defArray is larger than the attack of the neighbours so it doesn't need to enter the loop (you check specially for the first element).
It works for the third line because the last element in defArray is larger than the attack of the neighbours so it doesn't need to enter the loop (you check specially for the last element).
It doesn't work for any item in the loop after the first one because as soon as something in defArray is not larger than the attack of the neighbours you call break; and exit the loop. You need to check every element in defArray but the loop stops as soon as any element fails. Why are you calling break; anyway?
I haven't tested all the boundary conditions but removing the break; does seem to fix it...