Kurskal algorithm, Runtime Error in Kattis - c++

I've been trying to solve the Minimum Spanning Tree on Kattis. (https://open.kattis.com/problems/minspantree) The first test runs fine, the second gives an unspecified runtime error. I've been struggling with this for over a week. It must be some logical error, but no matter how much effort i'm putting into it, I can't see what's wrong.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <tuple>
using namespace std;
class DisjointSet {
public:
vector<int> parent, rank;
DisjointSet(int _size) {
parent.resize(_size);
rank.resize(_size); // Maybe this?
// make the sets
for (int i = 0; i < _size; i++) { // fill set
parent[i] = i;
rank[i] = 0;
}
}
void make_set(int v) {
parent[v] = v;
rank[v] = 0;
}
int find_set(int v) {
if (v == parent[v])
return v;
return parent[v] = find_set(parent[v]);
}
void union_sets(int a, int b) {
a = find_set(a);
b = find_set(b);
if (a != b) {
if (rank[a] < rank[b])
swap(a, b);
parent[b] = a;
if (rank[a] == rank[b])
rank[a]++;
}
}
};
bool sort_weight(const tuple<int, int, int> &one, const tuple<int, int, int> &two) {
return get<2>(one) < get<2>(two); // Weight
}
bool sort_node(const tuple<int, int, int> &one, const tuple<int, int, int> &two) {
if (get<0>(one) != get<0>(two)) {
return get<0>(one) < get<0>(two); // node one
}
return get<1>(one) < get<1>(two); // node two
}
int main()
{
int n_nodes = 0, n_arcs = 0;
int tmp_node1, tmp_node2, tmp_weight;
while (cin >> n_nodes >> n_arcs) { // Until the end
if (n_nodes == 0 && n_arcs == 0) { break; }
if (n_arcs < n_nodes - 1) { // If it is not possible to build a MST
cout << "Impossible\n";
}
else {
int cost = 0;
DisjointSet s(n_nodes); // make set
vector<tuple<int, int, int>> vArcs;
vector<tuple<int, int, int>> vResult;
vArcs.resize(n_arcs);
for (int i = 0; i < n_arcs; i++) {
cin >> tmp_node1 >> tmp_node2 >> tmp_weight;
vArcs[i] = make_tuple(tmp_node1, tmp_node2, tmp_weight);
}
sort(vArcs.begin(), vArcs.end(), sort_weight); // Sort by weight lowest to highest
for (int i = 0; i < n_arcs && vResult.size()<(n_nodes - 1); i++)
{
if (s.find_set(get<0>(vArcs[i])) != s.find_set(get<1>(vArcs[i]))) {
cost += get<2>(vArcs[i]);
vResult.push_back(vArcs[i]);
s.union_sets(get<0>(vArcs[i]), get<1>(vArcs[i]));
}
}
// We are done, order and print
sort(vResult.begin(), vResult.end(), sort_node);
cout << cost << "\n";
for (int i = 0; i < vResult.size(); i++)
{
cout << get<0>(vResult[i]) << " " << get<1>(vResult[i]) << "\n";
}
}
}
}

You need to read the whole input for each test case, even if the number of edges is below n - 1.

Related

Codeforces 519B Using Vectors vs Some Other Container

To solve 519B I created three vectors that each hold different numbers and occurrences of those numbers for each line. These vectors are also sorted.
eg if the line was 1 1 3 2, the vector would store <1, 2>, <2, 1>, <3, 1>
From there, I would compare one pair from one vector with the pair from the next vector to find the missing number.
This passes most test cases until there are a large number of numbers in each line. I actually saw the answer for this question, but it uses a different method to find the answer. However, I would like to know if there is a way to solve the question with "my way." I read online that using maps and other containers could yield a faster result, but I'm skeptical that using another container would really make that big of a difference. Any thoughts?
#include <iostream>
#include <vector>
#include <algorithm>
int has(std::vector<std::pair<int, int>> &error, int i) {
for (int j = 0; j < error.size(); j++) {
if (error[j].first == i) {
return j;
}
}
return -1;
}
std::vector<std::pair<int, int>> generate(int n) {
int temp;
std::vector<std::pair<int, int>> tempVec;
for (int i = 0; i < n; i++) {
std::cin >> temp;
int pos = has(tempVec, temp);
if (pos != -1) {
tempVec[pos].second++;
} else {
tempVec.push_back(std::make_pair(temp, 1));
}
}
return tempVec;
}
bool sortPair(const std::pair<int, int> &a, const std::pair<int, int> &b) {
return a.first < b.first;
}
int main() {
int n, temp;
std::cin >> n;
std::vector<std::pair<int, int>> a = generate(n), b = generate(n - 1), c = generate(n - 2);
std::sort(a.begin(), a.end(), sortPair);
std::sort(b.begin(), b.end(), sortPair);
std::sort(c.begin(), c.end(), sortPair);
bool found = false;
for (int i = 0; i < n - 1; i++) {
if (a[i] != b[i]) {
found = true;
std::cout << a[i].first << std::endl;
break;
}
}
if (!found) {
std::cout << a[n - 1].first << std::endl;
}
bool found2 = false;
for (int i = 0; i < n - 2; i++) {
if (b[i] != c[i]) {
found2 = true;
std::cout << b[i].first << std::endl;
break;
}
}
if (!found2) {
std::cout << b[n - 2].first << std::endl;
}
}

Wrong output in large inputs

Please help me out with this problem: https://cses.fi/problemset/task/1131/
I'm getting the wrong output for large values.
The algorithm is: computing the height of the left subtree and the right subtree by using an arbitrary node.
Thank you :)
#include <bits/stdc++.h>
#define int long long int
using namespace std;
bool visited[200005] = {false};
vector<vector<int>> vect(200005);
int height(int n) {
int m = 0, t=-1;
visited[n] = true;
for(auto x : vect[n]) {
if(visited[x] == false) {
t = height(x);
if(m < t)
m = t;
}
}
return m+1;
}
int treeDiameter(int n) {
int m1=0, m2=0, t=0;
visited[n] = true;
for(auto x : vect[n]) {
t = height(x);
if(t > m1) {
m2 = m1;
m1 = t;
}
else if(t > m2)
m2 = t;
}
return m1 + m2;
}
int32_t main() {
int n, m=999999;
cin >> n;
n--;
if(n > 1) {
while(n--) {
int a, b;
cin >> a >> b;
vect[a].push_back(b);
vect[b].push_back(a);
if(a < m) m = a;
}
// cout << m;
cout << treeDiameter(m);
} else cout << 0 << endl;
return 0;
}

Solving String Factoring

I'm trying to solve a question from kattis as shown here regarding string factorisation. I've tried adjusting my code for quite abit but it still seems theoretically correct. Not sure why it still fails for some of the test cases.
#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
string shortener (string input) {
map<string, int> freq;
int flag = 0;
for (int i = (input.length())/2; i >= 1 && !flag; i--) {
for (int d = 0; d + i + i <= input.length(); d++) {
if (input.substr(d, i) == input.substr(d + i, i)) {
freq[input.substr(d,i)]++;
flag = 1; // stop at this size
}
}
}
int largest = 0;
if (freq.empty()) return input;
//string largest;
auto x = max_element(freq.begin(), freq.end(),
[](const pair<string, int>& p1, const pair<string, int>& p2) {
return p1.second < p2.second; });
if (x->first == input) return input;
int a = input.find(x->first);
for (int i = 0; i < x->second ; i++) {
input.replace(a, x->first.length(), "");
a = input.find(x->first);
}
if (a != -1) {
if (!input.substr(0, a).empty())
input.replace(0, a, shortener(input.substr(0, a)));
if (!input.substr(a + x->first.length()-1, input.length()-1).empty())
input.replace(a + x->first.length()-1, input.length()-1, shortener(input.substr(a + x->first.length()-1, input.length()-1)));
//cout << input.substr(a + x->first.length()-1, input.length()-1) << endl;
input.replace(a, x->first.length(), shortener(x->first));
}
return input;
}
int main () {
string input;
cin >> input;
cout << shortener(input).length() << endl;
}
I know my code may not be the most efficient, but I'm hoping to find out what kind of test case might potentially break my code.

std::vector out of range for min-heap: C++

I've neglected to work on this code (or any other coding projects) for a while, so while I know what is basically wrong with the code, I've been having a hard time finding exactly where the vector is going out of range. I've been running gdb on it all morning to no avail. I'm trying to make a min-heap out of a vector "theData" in C++.
#include <iostream>
#include <vector>
#include <algorithm>
using std::vector;
using std::cin;
using std::cout;
using std::swap;
using std::pair;
using std::make_pair;
class HeapBuilder {
private:
vector<int> data_;
vector< pair<int, int> > swaps_;
void WriteResponse() const {
cout << swaps_.size() << "\n";
for (int i = 0; i < swaps_.size(); ++i) {
cout << swaps_[i].first << " " << swaps_[i].second << "\n";
}
}
void ReadData() {
int n;
cin >> n;
data_.resize(n);
for(int i = 0; i < n; ++i)
cin >> data_[i];
}
void makeMinHeap(vector<int> &theData, int i, int n) {
int minIndex;
int left = 2*i;
int right = 2*i + 1;
if (left < n && theData.at(left) < theData.at(i)) {
minIndex = left;
}
else if (right < n && theData.at(right) < theData.at(i)) {
minIndex = right;
}
if (minIndex != i) {
swap(theData.at(i), theData.at(minIndex));
swaps_.push_back(make_pair(i, minIndex));
makeMinHeap(theData, minIndex, n);
}
}
void GenerateSwaps() {
swaps_.clear();
int size = data_.size();
for (int i = (size/2); i >= 0; i--) {
makeMinHeap(data_, i, size);
}
}
public:
void Solve() {
ReadData();
GenerateSwaps();
WriteResponse();
}
};
int main() {
std::ios_base::sync_with_stdio(false);
HeapBuilder heap_builder;
heap_builder.Solve();
return 0;
}
You are not putting in a check for minIndex.
Look what happens when your left<=n and right <=n both fails, most likely when the whole recursion is about to stop, since you just check
minIndex != i
// ^-- default each time is garbage which in case last>n && right>n leaves it garbage
// hence when it comes to
if(minIndex!=i){
// It's actually true where it was suppose to break out n thus throws out_of_range
}
Quick n easy solution would be to add a flagcheck
bool flagcheck = false;
if(){ flagcheck = true; }
else if(){ flagcheck = true; }
if(minIndex!=i && flagcheck){}

Querying for a value that's bigger than X, while having another condition

I have list of pair [x;y] where x is unique and y can be duplicate(integers).
Here lies a problem:
Given a pair [x;y], find new pair [k;m], such that:
k > x
m >= y
k - x is minimized.
Now, I've solved this problem with this logic; I sort pairs by x, and then start naive O(n^2) algorithm on it. It seems to work fine, except it's too slow.
Can I do better?
The actual problem im trying to solve, is here: http://www.spoj.com/problems/VBOSS/
and my current code:
#include <stdio.h>
#include <utility>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
struct employee
{
int id;
int salary;
int height;
int parent_index;
int sub_ordinates;
int cur;
bool important;
bool operator < (const employee& e) const
{
if(height == e.height)
return salary > e.salary;
return (height > e.height);
}
};
// problem states explictly that no two employees
// have same salary.
struct salary_predicate
{
inline bool operator() (const employee& struct1, const employee& struct2)
{
return (struct1.salary > struct2.salary);
}
};
const int MAX_EMPLOYEES = 30000;
const int MAX_QUERIES = 200;
employee employees[MAX_EMPLOYEES];
int queries[MAX_QUERIES];
int main()
{
int test_cases;
scanf("%d", &test_cases);
while(test_cases--)
{
int employeeCount, queryCount;
scanf("%d %d", &employeeCount, &queryCount);
int i = 0;
int j = 0;
while(i < employeeCount)
{
employees[i].parent_index = -1;
employees[i].sub_ordinates = 0;
employees[i].cur = i;
employees[i].important = false;
scanf("%d %d %d", &employees[i].id, &employees[i].salary, &employees[i].height);
i++;
}
map<int, int> mapper;
while(j < queryCount)
{
scanf("%d", &queries[j]);
mapper.insert(pair<int, int>(queries[j], -1));
j++;
}
// now step1; sort employees structure
// based on SALARY!!
sort(employees, employees + employeeCount, salary_predicate());
for(int k = 0; k < employeeCount; k++)
{
employees[k].cur = k;
if(mapper.find(employees[k].id) != mapper.end())
{
mapper[employees[k].id] = k;
employees[k].important = true;
}
}
int found = 0;
for(int l = employeeCount - 1; l >= 0; l--)
{
int gef = l - 1;
// check out information about previous worker,
// he might give us some valuable information!
// with his help, we know if we can skip some shit :)
if(l + 1 < employeeCount && employees[l + 1].parent_index != -1)
{
// if previous employee is smaller than our current employee
// then we can skip some people, becase we know that answer cant be
// smalle than that :)
if(employees[l + 1].height <= employees[l].height)
gef = employees[l + 1].parent_index - 1;
}
// find boss!
for(int b = gef; b >= 0; b--)
{
if(employees[b].height >= employees[l].height)
{
employees[l].parent_index = b;
employees[b].sub_ordinates += employees[l].sub_ordinates + 1;
break;
}
}
// this bit makes sure if we have processed all necessay things,
// then we can basically stop our work.
if(employees[l].important) found++;
if(found == mapper.size()) break;
}
// time to print it out.
for(int b = 0; b < queryCount; b++)
{
int id = queries[b];
int index = mapper[id];
int parent_index = employees[index].parent_index;
int parent = parent_index < 0 ? 0 : employees[parent_index].id;
printf("%d %d\r\n", parent, employees[index].sub_ordinates);
}
}
return 0;
}
salary=x, and height=y.
I would start by eliminating all records where m<y or k<=x. Then find the item with the smallest k value out of what's left. Both of these should be linear, so your overall complexity should also be linear.
struct p {
int k, m;
};
p find_item(p xy, std::vector<p> &values) {
auto end = std::partition(values.begin(), values.end(),
[xy](p const &v) { return xy.k < v.k || xy.m >= v.m; });
return *std::min_element(values.begin(), end,
[](p const &a, p const &b) { return a.k < b.k; });
}