everyone, I have a weighted connected undirected graph, I need to find it's minimum spanning tree weight. On input I have numbers n(vertices amount), m(edges amount). And then m edges in format: A(out vert), B(in vert), C(weight). Here is input example:
3 3
1 2 1
2 3 2
3 1 3
I see it as a typical Prim algorithm, so I used it, but some tests are telling me that my code gives a wrong answer. Here it is:
#include <numeric>
#include <iostream>
using namespace std;
long long primAlgo(const int vertices, const vector<vector<long long>> &edges) {
vector<bool> visited(vertices, false);
vector<long long> minimal(vertices, 30001);
minimal[0] = 0;
for (size_t i = 0; i != vertices; ++i) {
int vert = -1;
for (size_t option = 0; option != vertices; ++option) {
if (!visited[option] && (vert == -1 || minimal[option] < minimal[vert]))
vert = option;
}
visited[vert] = true;
for (size_t to = 0; to != vertices; ++to) {
if (edges[vert][to] < minimal[to]) {
minimal[to] = edges[vert][to];
}
}
}
long long sum = 0;
for (size_t i = 0; i != vertices; ++i) {
sum += minimal[i];
}
return sum;
}
int main() {
int n, m;
cin >> n >> m;
int A, B;
long long C;
vector<vector<long long>> l(n, vector<long long> (n, 30001));
for (size_t i = 0; i != m; ++i) {
cin >> A >> B >> C;
l[A - 1][B - 1] = C;
l[B - 1][A - 1] = C;
}
long long ans = primAlgo(n, l);
cout << ans;
}
So I was wondering, if you know, what the problem may be.
Related
It is good array only if gcd(val[i],val[j])>1
Here,
gcd(a,b) = Greatest common divisor of two numbers.
Split the array has one parameter
Val: A integer array of n integer
Here are two examples.
Sample Input 0:
5 // no of value in an integer
2
3
2
3
3
Sample Output 0:
2
Sample Input 1:
5 //no of value in an integer
3
5
7
11
2
Sample Output 1:
5
example of sample input 0
subarray[1..3] ={2,3,2} here gcd(2,2)>1
subarray[4..5]={3,3} gcd(3,3)>1
#include <bits/stdc++.h>
using namespace std;
string ltrim(const string &);
string rtrim(const string &);
Now how to impelement the splitTheArray() function?
You need to find the minimum number of subarrays such that in each sub-array, first and last elements' gcd > 1. You can do it easily by O(Nˆ2) complexity.
int splitTheArray(vector<int> val) {
// implement this function
int sz = val.size();
if(sz == 0) return 0;
int ind = sz - 1;
int subarray = 0;
while(ind >= 0) {
for(int i = 0; i <= ind; i++) {
if(__gcd(val[ind], val[i]) > 1) {
subarray++;
ind = i-1;
break;
}
}
}
return subarray;
}
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
int max(int a, int b)
{
return (a > b) ? a : b;
}
int min(int a, int b)
{
return (a < b) ? a : b;
}
int solve(vector<int> vec)
{
int n = gcd(vec[0], vec[vec.size() - 1]);
if (n > 1)
return 0;
int con = 0 , flag = 0 , j=0 , i=0 , flag2=0;
for (i = j; i < vec.size()/2; i++)
{
i = j;
if (i >= vec.size())
break;
int f = vec[i];
flag = 0;
for (j = i+1; j < vec.size(); j++)
{
int l = vec[j];
int ma = max(f, l);
int mi = min(f, l);
n = gcd(ma, mi);
if (flag)
{
if (n > 1)
con++;
else
break;
}
if (n > 1)
{
flag = 1;
flag2 = 1;
con++;
}
}
}
if (!flag2)
return vec.size();
return con;
}
int main()
{
int n;
cin >> n;
vector<int> vec;
for (int i = 0; i < n; i++)
{
int tm;
cin >> tm;
vec.emplace_back(tm);
}
cout<<solve(vec);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define int long long int
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
void solve()
{
int n,i,j;
cin>>n;
int A[n+1],DP[n+1];
for(i=1;i<=n;i++)
cin>>A[i];
memset(DP,0,sizeof(DP));
unordered_map<int,int> M;
for(i=1;i<=n;i++)
{
vector<int> Fact;
Fact.push_back(A[i]);
for(j=2;j*j<=A[i];j++)
{
if(A[i]%j==0)
{
if(j*j==A[i])
{
Fact.push_back(j);
}
else
{
Fact.push_back(j);
Fact.push_back(A[i]/j);
}
}
}
int ans=DP[i-1]+1;
for(j=0;j<Fact.size();j++)
{
if(M.find(Fact[j])==M.end())
{
M[Fact[j]]=DP[i-1];
}
else
{
ans=min(ans,M[Fact[j]]+1);
}
}
DP[i]=ans;
}
cout<<DP[n]<<endl;
}
int32_t main()
{
boost;
int t=1;
// cin>>t;
for(int i=1;i<=t;i++)
{
//cout<<"Case #"<<i<<": ";
solve();
}
}
Time Complexity: N*Sqrt(max(A[i]))
P.S There can be a optimization of calculation of factor using the sieve instead of calculating factor every time for every number.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int>a(n);
for(int i=0;i<n;i++){
cin>>a[i];
}
vector<int>dp(n+1,0);
dp[n-1]=1;
for(int i=n-2;i>=0;i--){
dp[i]=1+dp[i+1];
for(int j=i+1;j<n;j++){
if(__gcd(a[i],a[j])>1)
dp[i]=min(dp[i],1+dp[j+1]);
}
}
cout<<dp[0];
return 0;
}
I did implement Sieve prime generator. The code is pretty fast and consumes less memory. https://www.spoj.com/problems/PRIME1/
But I get "Wrong Answer" when I submit the solution. People online seem to just make the set the max to 32000 and run the solution. I don't exactly get where am I actually wrong? Or Is it just an extra newline (if possible) that makes the solution to be incorrect?
#include <iostream>
#include <unordered_map>
using namespace std;
int main(void) {
unordered_map<long long int, bool> notPrime;
notPrime[0] = true;
notPrime[1] = true;
for (long long int x = 2; x < 100000; x++) {
if (notPrime[x]) continue;
for (long long int u = 2 * x; u < 100000; u += x)
notPrime[u] = true;
}
int n;
cin >> n;
while (n--) {
long long int s, e;
cin >> s >> e;
if (s < 0)
s = 0;
for (long long int i = s; i <= e; i++) {
if (!notPrime[i]) {
cout << i << '\n';
}
}
if (n)
puts("");
}
return 0;
}
I am trying to solve the Non-Divisible Subset problem from Hackerrank (https://www.hackerrank.com/challenges/non-divisible-subset). I am trying to use the idea that if the sum of a and b is divisible by k, then a%k+b%k = k, however, it's not working very well.
Here is what I've written so far:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
int k;
cin >> n;
cin >> k;
int j;
vector<int>numbers;
vector<int>remainders;
for(int i = 0; i < n; i++) {
int z;
cin >> z;
numbers.push_back(z);
}
for (vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++) {
j = *it % k;
remainders.push_back(j);
}
for(vector<int>::iterator it2 = remainders.begin(); it2 != remainders.end(); it2++) {
int remainderCount = 0;
int otherRemainderCount = 0;
otherRemainderCount = std::count(remainders.begin(), remainders.end(), k-*it2);
remainderCount = std::count(remainders.begin(), remainders.end(), *it2);
if (remainderCount > otherRemainderCount) {
theChosenOne = *it2;
} else if (otherRemainderCount > remainderCount) {
theChosenOne = k-*it2;
}
cout << theChosenOne << endl;
}
return 0;
}
I created a vector for the remainders and I am using the std::cout function to find out which remainder appears more in the vector. If K would be 5, *it2 = 4, and k-*it2 = 1. If *it2 appears more times, then I would choose *it2. Otherwise, I would choose k-*it2.
Your solution looks to be on the right track, but there is some change that is needed.
You basically need to hash the numbers in the array to proper location.
Have an array rem[k] initialised to 0.
Iterate over the n numbers in the array, and do the following:
rem[array[i]%k]++;
Now you have to deal with only the rem[] array, to find the maximum subset. The rem array has size of maximum k<=100. Make use of the small size of rem[] array to find the solution efficiently.
Edit: Adding the code for you.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n,i,k;
cin>>n>>k;
int arr[n];
int rem[k]={0};
for(i=0;i<n;i++)
{
cin>>arr[i];
}
for(i=0;i<n;i++)
{
rem[arr[i]%k]++;
}
int count = 0;
for(i=1;i<=k/2;i++)
{
count = count + max(rem[i],rem[k-i]);
}
count = count + (rem[0]>0?1:0);
if(k%2==0)
{
count = count - rem[k/2];
if(rem[k/2]>0)
count = count + 1;
}
cout<<count;
return 0;
}
After you have found out the contents of the rem[] array, its time to find the maximum subset. If you select rem[1] then you cannot select rem[k-1] as any two numbers, one from rem[1] and another from rem[k-1] can be summed together which will be divisible by k that we don't want. So we find whichever is maximum out of rem[i] and rem[k-i] and add it to the count
My code uses the above logic..
Hope it helps!!!
int main() {
int n,k;
cin>>n>>k;
vector <int> a(n);
vector <int> r(k,0);
for(int i=0;i<n;i++)
{
cin>>a[i];
r[a[i]%k]++;
}
int ctr=min(1,r[0]);
for(int a=1;a<(k/2+1);a++)
{
if(a!=k-a)
ctr+=max(r[a],r[k-a]);
}
if(k%2==0&&r[k/2]!=0)
ctr++;
cout<<ctr;
return 0;
}
This seemed to work
#include <stdio.h>
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int main() {
int n, k, a, total = 0;
scanf("%d %d", &n, &k);
int mods[k];
for (int i = 0; i < k; i++)
mods[i] = 0;
while (n--) {
scanf("%d", &a);
mods[a % k]++;
}
// can only have 1 value congruent to 0 mod k
total += min(1, mods[0]);
// if even, can only have 1 value congruent to k/2 mod k
if (k % 2 == 0)
total += min(1, mods[k / 2]);
// for all others, pick max of those k and n-k mod k
for (int d = 1; d < (k + 1) / 2; d++) { // for all others,
total += max(mods[d], mods[k - d]);
}
printf("%d", total);
return 0;
}
My problem is that I hit an obstacle while I was solving some exercises.
The source of the problem is that I have to write a program which sort descending an array by the number of each element's divisors, but when two element has the same number of divisors it should sort ascending those values.
My code so far:
#include <iostream>
#include <fstream>
using namespace std;
int cntDiv(int n) //get number of divisors
{
int lim = n;
int c = 0;
if(n == 1)
return 1;
for(int i = 1; i < lim; i++)
{
if(n % i == 0)
{
lim = n / i;
if(lim != i)
c++;
c++;
}
}
return c;
}
int main()
{
ifstream fin("in.txt");
int n, i, j;
fin >> n;
int v[n];
for(i = 0; i < n; i++)
fin >> v[i];
int div[n];
for(i = 0; i < n; i++)
div[i] = cntDiv(v[i]);
for(i = 0; i < n - 1; i++)
{
for(j = i + 1; j < n; j++)
{
if(div[i] < div[j] && div[i] != div[j]) //if the number of divisors are different
{
int t = v[i];
v[i] = v[j];
v[j] = t;
t = div[i];
div[i] = div[j];
div[j] = t;
}
if(div[i] == div[j] && v[i] > v[j]) //if the number of divisors are the same
{
int t = v[i];
v[i] = v[j];
v[j] = t;
}
}
}
for(i = 0; i < n; i++)
{
cout << v[i] << " ";
}
return 0;
}
In.txt:
5
12 20 4 100 13
Output:
100 12 20 4 13
Although it works fine with this one and many other. For bigger inputs it exceeds the time limit which is 0.1s. Any advice how should I rewrite the sorting? (I wrote bubble sort because I could not implement sorting array by property via quicksort)
Use an array of structures. The structure would contain the original value and a container of divisors:
struct Number_Attributes
{
int number;
std::list<int> divisors;
};
You can then write a custom comparator function and pass to std::sort:
bool Order_By_Divisors(const Number_Attributes& a,
const Number_Attributes& b)
{
return a.divisors.size() < b.divisors.size();
}
The sorting then becomes:
#define ARRAY_CAPACITY (20U)
Number_Attributes the_array[ARRAY_CAPACITY];
//...
std::sort(&array[0], &array[ARRAY_CAPACITY], Order_By_Divisors);
The generation of divisors is left as an exercise for the OP.
Reworking your code with std::sort:
std::vector<std::pair<int, int>> customSort(const std::vector<int>& v)
{
std::vector<std::pair<int, int>> ps;
ps.reserve(v.size());
// We don't have zip sort :/
// So building the pair
for (auto e : v)
{
ps.emplace_back(e, cntDiv(e));
}
std::sort(ps.begin(), ps.end(), [](const auto&lhs, const auto& rhs) {
// descending number of divisors, increasing value
return std::make_tuple(-lhs.second, lhs.first)
< std::make_tuple(-rhs.second, rhs.first);
});
return ps;
}
int main()
{
const std::vector<int> v = {12, 20, 4, 100, 13};
const auto res = customSort(v);
for(const auto& p : res)
{
std::cout << p.first << " ";
}
}
Demo
I wanted to count the number of groups in an undirected graphs in c++.I was trying using bfs but was unsuccessful.I have been given a range of numbers [L,R] (or think of these ranges as number of vertices) and i have to find the number of groups.How do i do this?
Like if i have (Input):
1 3
2 5
6 9
Output:
2
As there are 2 groups.
My code:
bool visited[MAX];
vector<int> v[MAX];
int solve(int x)
{
queue<int> q;int ans=0;
q.push(x);
if(v[x].empty())
{
ans++;
}
while(!q.empty())
{
int curr = q.front();
visited[curr] = true;
q.pop();
for(int i = 0; i < v[curr].size(); i ++)
{
if(!visited[v[curr][i]])
{
q.push(v[curr][i]);
visited[v[curr][i]] = true;
}
}
if(v[curr].empty()) ans++;
}
return ans;
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
int l,r,n,ans=0,min_,max_=0;
scanf("%d",&n);
for(int i = 0; i < n; i ++)
visited[i] = false;
for(int j=0;j<n;j++)
{
scanf("%d",&l);scanf("%d",&r);
for(int i=l;i<r;i++)
{
v[i].push_back(i+1);
min_ = min(min_,i);
max_ = max(max_,i+1);
}
}
printf("%d\n",solve(min_));
}
return 0;
}
Let's take a look at how many edges are created in the worst case. It is N * (MAX_R - MIN_L), which is 10^5 * 2000 under given constraints. You program runs out of memory and gets runtime error. A more efficient algorithm is required. Here is a simple solution that uses only O(MAX_R) memory and O(N + MAX_R) time.
vector<int> start(MAX_R + 1);
vector<int> end(MAX_R + 1);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int low;
int high;
cin >> low >> high;
start[low]++;
end[high]++;
}
int res = 0;
int sum = 0;
for (int pos = 0; pos <= MAX_R; pos++) {
if (sum == 0 && start[pos] > 0)
res++;
sum += start[pos] - end[pos];
}
cout << res << endl;
There is no need for bfs or any other graph algorithms in this problem.
You could fix your original solution by avoiding multiple edges in the graph(there is no need to create an edge from i to i + 1 if it already exists, but I am not sure if your original solution is correct).
Looks like you should start by changing to vector<pair<int,int>> v;. Then to populate v you should use:
scanf("%d", &l);scanf("%d", &r);
v.push_back(make_pair(l, r);
Then your function should become something like:
int solve(){
vector<pair<int, int>> results;
for(auto& vIndex : v){
auto resultIndex = find_if(results.begin(), results.end(), [vIndex](const pair<int, int>& i){return vIndex.first >= i.first && vIndex.first <= i.second || vIndex.second >= i.first && vIndex.second <= i.second;});
if(resultIndex == results.end()){
results.push_back(vIndex);
}else{
resultIndex->first = min(vIndex.first, resultIndex->first);
resultIndex->second = max(vIndex.second, resultIndex->second);
}
}
return results.size();
}
You can see this in action here: http://ideone.com/MDQBOr Just hard code your desired inputs into v.