I have an undirected weighted graph and want to find the minimum sum of all cycles edges.
That means if I have no cycle, the answer is 0.
If I have one cycle the answer is the minimum edge weight of that cycle.
And if I have more than one cycle it's the sum of those minimum weights.
My algorithm I implemented, uses some kind of Prims algorithm.
I just add the heaviest edges and when a cycle would be formed the weight is summed to the answer value instead.
I thought it is correct as all my test cases show the right answer.
But somewhere has to be an error, I just couldn't find it yet.
struct connection {
int a, b, cost;
bool operator<(const connection rhs) const {
return cost < rhs.cost || (cost == rhs.cost && (a < rhs.a || (a == rhs.a && b < rhs.b)));
}
};
int n, m, researchers; // Amount of vertices, edges
std::list<connection> *adj; // Array of adjancency lists
std::list<int> *used;
std::set<connection> priorityQ;
void addEdge(int v, int w, int cost) {
connection temp;
temp.a = v;
temp.b = w;
temp.cost = cost;
adj[v].push_back(temp);
temp.a = w;
temp.b = v;
adj[w].push_back(temp);
}
bool isUsed(int u, int v) {
for (std::list<int>::iterator it = used[u].begin(); it != used[u].end(); ++it) {
int te = *it;
if (te == v) return true;
}
return false;
}
void expand(int u) {
for (std::list<connection>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
connection v = *it;
if (isUsed(u, v.b)) continue;
used[v.b].push_back(u);
used[u].push_back(v.b);
priorityQ.insert(v);
}
}
void PrimR(int u, bool added[]) {
added[u] = true;
expand(u);
}
// Prim algorithm
void Prim(int u, bool added[]) {
added[u] = true;
expand(u);
while (priorityQ.size() > 0) {
connection now = *priorityQ.rbegin();
priorityQ.erase(*priorityQ.rbegin());
if (added[now.b]) {
researchers += now.cost;
}
else {
PrimR(now.b, added);
}
}
}
int main()
{
int t;
// loop over all test cases
scanf("%d ", &t);
for (int i = 1; i <= t; i++) {
// read input nodes n, connections m
scanf("%d %d", &n, &m);
adj = new std::list<connection>[n];
//read connections and save them
for (int j = 0; j < m; j++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
addEdge(a - 1, b - 1, c);
}
researchers = 0;
// Use of prim with heaviest edges first
bool *added = new bool[n];
used = new std::list<int>[n];
for (int j = 0; j < n; j++) {
added[j] = false;
}
for (int j = 0; j < n; j++) {
if (!added[j]) {
Prim(j, added);
}
}
// print desired output
printf("Case #%d: %d\n", i, researchers);
delete[] adj;
delete[] added;
delete[] used;
}
return 0;
}
Do you know what I'm doing wrong?
I didn't consider, that between two nodes there could be multiple connections.
My following code solves this:
struct connection {
int a, b, cost, id;
bool operator<(const connection rhs) const {
return cost < rhs.cost || (cost == rhs.cost && id < rhs.id);
}
};
int n, m, researchers; // Amount of vertices, edges
std::list<connection> *adj; // Array of adjancency lists
std::set<connection> priorityQ;
void addEdge(int v, int w, int cost, int id) {
connection temp;
temp.a = v;
temp.b = w;
temp.cost = cost;
temp.id = id;
adj[v].push_back(temp);
temp.a = w;
temp.b = v;
adj[w].push_back(temp);
}
void deleteEdge(int v, int w, int id) {
for (std::list<connection>::iterator it = adj[v].begin(); it != adj[v].end(); ++it) {
if ((*it).id == id) {
adj[v].erase(it);
break;
}
}
for (std::list<connection>::iterator it = adj[w].begin(); it != adj[w].end(); ++it) {
if ((*it).id == id) {
adj[w].erase(it);
break;
}
}
}
void expand(int u) {
for (std::list<connection>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
connection v;
v.a = (*it).a < (*it).b ? (*it).a : (*it).b;
v.b = (*it).a < (*it).b ? (*it).b : (*it).a;
v.cost = (*it).cost;
v.id = (*it).id;
priorityQ.insert(v);
}
}
void PrimR(int u, bool added[]) {
added[u] = true;
expand(u);
}
// Prim algorithm
void Prim(int u, bool added[]) {
added[u] = true;
expand(u);
while (priorityQ.size() > 0) {
connection now = *priorityQ.rbegin();
priorityQ.erase(*priorityQ.rbegin());
deleteEdge(now.a, now.b, now.id);
if (added[now.b] && added[now.a]) {
researchers += now.cost;
}
else if (added[now.b]) {
PrimR(now.a, added);
}
else if (added[now.a]) {
PrimR(now.b, added);
}
}
}
int main()
{
int t;
// loop over all test cases
scanf("%d ", &t);
for (int i = 1; i <= t; i++) {
// read input nodes n, connections m
scanf("%d %d", &n, &m);
adj = new std::list<connection>[n];
//read connections and save them
for (int j = 0; j < m; j++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
addEdge(a - 1, b - 1, c, j);
}
researchers = 0;
// Use of prim with heaviest edges first
bool *added = new bool[n];
for (int j = 0; j < n; j++) {
added[j] = false;
}
for (int j = 0; j < n; j++) {
if (!added[j]) {
Prim(j, added);
}
}
// print desired output
printf("Case #%d: %d\n", i, researchers);
delete[] adj;
delete[] added;
}
return 0;
}
You can use Floyd-Warshall algorithm.
The Floyd-Warshall algorithm finds shortest path between all pairs of vertices.
And this shortest path to (u,u) -> (u,u) is the answer you're finding after considering every possible vertex u.
The algorithm run time is O(n^3).
Related
I have the queue functions and I have to use them to count the number of graph components. These are my functions:
struct TQueue {
int value;
TQueue * next;
};
void QueueInit(TQueue * & a_head, TQueue * & a_tail) {
a_head = NULL;
a_tail = NULL;
};
bool IsQueueEmpty(TQueue * a_head) {
return !a_head;
};
void Enqueue(TQueue * & a_head, TQueue * & a_tail, int a_val) {
TQueue * l_hlp = new TQueue;
l_hlp->value = a_val;
l_hlp->next = NULL;
if (a_tail) a_tail->next = l_hlp;
if (!a_head) a_head = l_hlp;
a_tail = l_hlp;
}
int Dequeue(TQueue * & a_head, TQueue * & a_tail) {
int l_val = a_head->value;
TQueue * l_hlp = a_head;
a_head = a_head->next;
if (!a_head) a_tail = NULL;
delete l_hlp;
return l_val;
};
void EmptyQueue(TQueue * & a_head, TQueue * & a_tail) {
TQueue * l_hlp;
while (a_head) {
l_hlp = a_head;
a_head = a_head->next;
delete l_hlp;
}
a_tail = NULL;
};
And this is my main() function and some variables:
// constant - number of vertexes
const int n = 9;
// queue declaration
TQueue *phead, *ptail;
QueueInit(phead, ptail);
// array of distanc
int dist[n];
// distanc array initialization
for (int i = 0; i < n; i++) dist[i] = -1;
// current distance
int d = 0;
// processingvertex
int v;
// number of components
int c = 0;
I prefer to use stack and DFS but it's a school projec so I must to use queue and BFS algorithm.
The approach is same as you would do in a dfs based approach. Here is a general bfs implementation using queue which you can modify easily for your purpose(i.e.using a custom queue)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void bfs(int src, vector<bool>& vis, vector<vector<int>>& adj) {
queue<int> q;
q.push(src);
vis[src] = true;
while(!q.empty()) {
int u = q.front(); q.pop();
vis[u] = true;
for(int v : adj[u]) {
if(!vis[v]) q.push(v);
}
}
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> adj(n);
for(int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
int count = 0;
vector<bool> vis(n);
for(int i = 0; i < n; i++) {
if(!vis[i]) {
bfs(i, vis, adj);
count++;
}
}
cout << count << '\n';
}
Variables reference
n : number of nodes in graph
m : number of edges in graph
adj : adjacency list representation of graph
vis : array to store if node is visited or not
count : number of connected components in graph
Example Test Case
Input:
6 3
1 5
0 2
2 4
Output:
3
You can refer to this post on mathematics stack exchange for understanding the algorithm: Finding connected components in a graph using BFS
This is my attempt to code compute components and assign vertices to components:
for (int i = 0; i <= n - 1; i++) visited[i] = false;
c = 0;
while (1) {
c++;
all = true;
for (int i = 0; i < n; i++)
if (!visited[i]) {
all = false;
visited[i] = c;
fronta::Enqueue(phead, ptail, i);
break;
}
if (all) {
c--;
break;
}
fronta::Enqueue(phead, ptail, 0);
visited[0] = true;
while (!fronta::IsQueueEmpty(phead)) {
v = fronta::Dequeue(phead, ptail);
//cout << "processing vertex: " << v << endl;
for (int j = 0; j < n; j++) {
if (gr3[v][j] && !visited[j]) {
fronta::Enqueue(phead, ptail, j);
visited[j] = true;
}
}
}
}
But it doesn't work very well...
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am trying to solve an algorithm problem (MST with Kruskal algorithm). It works sometimes and doesn't work sometimes (with runtime error). I solved this problem with another approach, but I want to figure out what is wrong with this code for future problems. I guess it is the memory problem, but I can't find out for two days.
typedef struct edges
{
struct edges *nextNode;
int weight;
int src;
int dest;
}EDGES;
typedef struct vertex
{
EDGES *edgePtr;
int verNum;
int weight;
COLOR color;
}VERTEX;
typedef struct setTree
{
struct setTree *parent;
int verNum;
int rank;
}SETNODE;
SETNODE *findSet(SETNODE *tree)
{
if (tree != tree->parent)
tree->parent = findSet(tree->parent);
return tree->parent;
}
void makeSet(SETNODE *tree, int vernum)
{
tree->parent = tree;
tree->verNum = vernum;
tree->rank = 0;
}
int linkSet(SETNODE *x, SETNODE *y)
{
SETNODE *x_root = findSet(x);
SETNODE *y_root = findSet(y);
if (x_root->rank > y_root->rank)
y_root->parent = x_root;
else if (x_root->rank < y_root->rank)
{
x_root->parent = y_root;
}
else
{
y_root->parent = x_root;
++x_root->rank;
}
return 1;
}
int unionSet(SETNODE *x, SETNODE *y)
{
return linkSet(x, y);
}
void MST_Kruskal(VERTEX **graph, int N, EDGES **edgeList, int edgeNum)
{
SETNODE *set[MAXN];
EDGES *result[MAXN*(MAXN - 1)];
EDGES *tmp[MAXN];
int edgeCnt = 0;
int tmpVerNum1, tmpVerNum2;
for (int i = 0; i < N; ++i)
{
set[i] = new SETNODE;
}
for (int i = 0; i < N; ++i)
{
makeSet(set[i], (i + 1));
}
mergeSort(edgeList, tmp, 0, edgeNum - 1);
/*for (int i = 0; i < edgeNum; ++i)
printf("%d->%d : %d\n", edgeList[i]->src, edgeList[i]->dest, edgeList[i]->weight);
*/
for (int i = 0; i < edgeNum; ++i)
{
tmpVerNum1 = edgeList[i]->src; tmpVerNum2 = edgeList[i]->dest;
if (findSet(set[tmpVerNum1 - 1]) != findSet(set[tmpVerNum2 - 1]))
{
int success = unionSet(set[tmpVerNum1 - 1], set[tmpVerNum2 - 1]);
if (success)
result[edgeCnt++] = edgeList[i];
}
}
printf("%d\n", edgeCnt);
for (int i = 0; i < edgeCnt; ++i)
{
printf("%d %d %d\n", result[i]->src, result[i]->dest, result[i]->weight);
}
for (int i = 0; i < N; ++i)
{
delete set[i];
}
}
For mergeSort, there's some kind of restriction with this problem that if weight is same between edges, there should be less vertex number first.
void merge(EDGES **arr, EDGES **tmp, int left, int middle, int right)
{
int i = left, j = middle + 1, k = left, l;
while (i <= middle && j <= right)
{
if (arr[i]->weight < arr[j]->weight)
{
tmp[k++] = arr[i++];
}
else if (arr[i]->weight == arr[j]->weight)
{
if (arr[i]->src < arr[j]->src)
tmp[k++] = arr[i++];
else if (arr[i]->src == arr[j]->src)
{
if (arr[i]->dest <= arr[j]->dest)
tmp[k++] = arr[i++];
else
tmp[k++] = arr[j++];
}
else
tmp[k++] = arr[j++];
}
else
{
tmp[k++] = arr[j++];
}
}
if (i > middle)
{
for (l = j; l <= right; l++)
{
tmp[k++] = arr[l];
}
}
else
{
for (l = i; l <= middle; l++)
{
tmp[k++] = arr[l];
}
}
for (l = left; l <= right; l++)
{
arr[l] = tmp[l];
}
}
void mergeSort(EDGES **arr, EDGES **tmp, int left, int right)
{
int middle = (left + right) / 2;
if (left < right)
{
mergeSort(arr, tmp, left, middle);
mergeSort(arr, tmp, middle + 1, right);
merge(arr, tmp, left, middle, right);
}
}
I think the problem lies in the declaration of tmp array. You have used it as a temporary array for the merge function in mergeSort.
I am assuming maxN is the maximum number of vertices in the graph. Hence the maximum number of edges in the graph can be maxN*(maxN-1). You have declared the size of result to be that and not tmp when infact the size of result should be maxN (maxN-1 to be precise since it will consist of edges representing a MST at the end) and the size of tmp should be maxN*(maxN-1) since the size of edgeList (which is being sorted using tmp array), i.e., edgeNum can be anywhere between 0 and maxN*(maxN-1).
In general, the fewer pointers you use means you are less likely to run into memory problems. Make sure that you aren't accidentally accessing members of a nullptr, or forgetting to pass an address to a function. It would be helpful if you could give us more information on the error :)
Here is an implementation of Kruskal that I wrote a while back. It makes heavy use of the STL and no pointers while simulating a linked list for the EdgeList using a pre-allocated array:
#include <cstdio>
#include <vector>
#include <queue>
#include <functional>
#include <algorithm>
const int MAXSZ = 1010;
struct Edge
{
static int cnt;
int from, to, weight, next;
} edges[MAXSZ * 2], full[MAXSZ * 2];
int Edge::cnt = 1;
int head[MAXSZ]; // for EdgeList impl
int bigb[MAXSZ]; // for DisjointSet impl
int find(const int c) // DisjointSet `find`
{
if (bigb[c] == c)
return c;
bigb[c] = find(bigb[c]);
return bigb[c];
}
void addEdge(const int a, const int b, const int w) // add edges to EdgeList from pure data
{
edges[Edge::cnt].from = a;
edges[Edge::cnt].to = b;
edges[Edge::cnt].weight = w;
edges[Edge::cnt].next = head[a];
head[a] = Edge::cnt;
++Edge::cnt;
bigb[find(a)] = bigb[find(b)] = std::min(find(a), find(b)); // needed to init DisjointSet
}
void addEdge(const Edge &base) // copy insert to EdgeList
{
edges[Edge::cnt] = base;
edges[Edge::cnt].next = head[base.from];
head[base.from] = Edge::cnt;
++Edge::cnt;
bigb[find(base.from)] = bigb[find(base.to)] = std::min(find(base.from), find(base.to));
}
int main()
{
int m, n;
scanf("%d%d", &m, &n);
auto cmp = [](const int &l, const int &r) { return full[l].weight > full[r].weight; };
std::priority_queue<int, std::vector<int>, std::function<bool(int, int)> > pq(cmp); // Used for kruskal
/* input */
for (int i = 1; i <= n; ++i)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
full[i].from = a;
full[i].to = b;
full[i].weight = w;
pq.push(i);
bigb[full[i].from] = full[i].from;
bigb[full[i].to] = full[i].to;
}
int sum = 0;
for (int vis = 0; !pq.empty(); pq.pop())
{
auto cur = full[pq.top()];
if (find(cur.to) == vis && find(cur.from) == vis)
continue; // if it leads back to something we already have
addEdge(cur);
addEdge(cur.to, cur.from, cur.weight); // other direction
vis = std::min(find(cur.to), find(cur.from));
printf("%d -> %d, %d\n", cur.from, cur.to, cur.weight);
sum += cur.weight;
//debug*/ for (int i=1; i<=m; ++i) printf("%3d", i); printf("\n"); for (int i=1; i<=m; ++i) printf("%3d", bigb[i]); printf("\n\n");
}
printf("total: %d\n", sum);
return 0;
}
/* test data
first line: verticies, edges
next #edges lines: from, to, weight
3 3
1 2 3
3 2 1
3 1 2
5 6
1 2 2
1 4 1
2 3 2
3 4 -2
3 5 1
4 5 9
*/
The question is described above. Basically, the input is vector<stack<int>>& piles and n, output is the max value for all n coins from any of the piles.
The only solution I can think of is to use backtracking for each pile, i.e. piles[0] is chosen i coins, then recursively call functions on piles[1...m-1] and n - i. And record max value for all possible combinations. I feel like this can be solved by dynamic-programming, however, due the constrain n, it's hard for me to build a dp equation.
Any better solution than backtracking?
There are m piles. Every pile p offers n+1 contributions of
(label, gain, cost):
for i from 0 upto n have ("pile {p}, {i} taken", sum of top i values, i).
The sum of costs must be equal (or less when negative numbers) to n, gain maximal.
The rest is up to the algorithm: whether you sort descending by ((double)gain)/cost or whatever.
This is definately nHr combination.
I would use some code like this.. p = number of piles, n = coins taken.
calc_sum is a function to record maximum value.
nHr h(p, n);
while(h.next()) {
for(int i=0; i<h.size(); i++) take_coins_from_a_pile(h[i]);
calc_sum();
}
And this is nHr library of my own.
#pragma once
#include <exception>
class NRexception : public std::exception
{
public:
virtual const char* what() const throw() {
return "Combination : N, R should be positive integer!!";
}
};
class Combination
{
public:
Combination(int n, int r);
virtual ~Combination() { delete [] ar;}
int& operator[](unsigned i) {return ar[i];}
bool next();
int size() {return r;}
static int factorial(int n);
protected:
int* ar;
int n, r;
};
class nCr : public Combination
{
public:
nCr(int n, int r);
bool next();
int count() const;
};
class nTr : public Combination
{
public:
nTr(int n, int r);
bool next();
int count() const;
};
class nHr : public nTr
{
public:
nHr(int n, int r) : nTr(n,r) {}
bool next();
int count() const;
};
class nPr : public Combination
{
public:
nPr(int n, int r);
virtual ~nPr() {delete [] on;}
bool next();
void rewind();
int count() const;
private:
bool* on;
void inc_ar(int i);
};
#include "combi.h"
#include <set>
#include<cmath>
Combination::Combination(int n, int r)
{
//if(n < 1 || r < 1) throw NRexception();
ar = new int[r];
this->n = n;
this->r = r;
}
int Combination::factorial(int n)
{
return n == 1 ? n : n * factorial(n-1);
}
int nPr::count() const
{
return factorial(n)/factorial(n-r);
}
int nCr::count() const
{
return factorial(n)/factorial(n-r)/factorial(r);
}
int nTr::count() const
{
return pow(n, r);
}
int nHr::count() const
{
return factorial(n+r-1)/factorial(n-1)/factorial(r);
}
nCr::nCr(int n, int r) : Combination(n, r)
{
if(r == 0) return;
for(int i=0; i<r-1; i++) ar[i] = i + 1;
ar[r-1] = r-1;
}
nTr::nTr(int n, int r) : Combination(n, r)
{
for(int i=0; i<r-1; i++) ar[i] = 1;
ar[r-1] = 0;
}
bool nCr::next()
{
if(r == 0) return false;
ar[r-1]++;
int i = r-1;
while(ar[i] == n-r+2+i) {
if(--i == -1) return false;
ar[i]++;
}
while(i < r-1) ar[i+1] = ar[i++] + 1;
return true;
}
bool nTr::next()
{
ar[r-1]++;
int i = r-1;
while(ar[i] == n+1) {
ar[i] = 1;
if(--i == -1) return false;
ar[i]++;
}
return true;
}
bool nHr::next()
{
ar[r-1]++;
int i = r-1;
while(ar[i] == n+1) {
if(--i == -1) return false;
ar[i]++;
}
while(i < r-1) ar[i+1] = ar[i++];
return true;
}
nPr::nPr(int n, int r) : Combination(n, r)
{
on = new bool[n+2];
for(int i=0; i<n+2; i++) on[i] = false;
for(int i=0; i<r; i++) {
ar[i] = i + 1;
on[i] = true;
}
ar[r-1] = 0;
}
void nPr::rewind()
{
for(int i=0; i<r; i++) {
ar[i] = i + 1;
on[i] = true;
}
ar[r-1] = 0;
}
bool nPr::next()
{
inc_ar(r-1);
int i = r-1;
while(ar[i] == n+1) {
if(--i == -1) return false;
inc_ar(i);
}
while(i < r-1) {
ar[++i] = 0;
inc_ar(i);
}
return true;
}
void nPr::inc_ar(int i)
{
on[ar[i]] = false;
while(on[++ar[i]]);
if(ar[i] != n+1) on[ar[i]] = true;
}
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; });
}
I can iterate over the subsets of size 1
for( int a = 0; a < size; a++ ) {
or subsets of size 2
for( int a1 = 0; a1 < size; a1++ ) {
for( int a2 = a1+1; a2 < size; a2++ ) {
or 3
for( int a1 = 0; a1 < size; a1++ ) {
for( int a2 = a1+1; a2 < size; a2++ ) {
for( int a3 = a2+1; a3 < size; a3++ ) {
But how to do this for subsets of size n?
This does the job, based on an answer by Adam Rosenfield
void iterate(int *a, int i, int size, int n)
{
int start = 0;
if( i > 0 ) start = a[i-1]+1;
for(a[i] = start; a[i] < n; a[i]++) {
if(i == n-1) {
// a is the array of indices of size n
for( int k = 0; k < size; k++ ) {
printf("%d ",a[k]);
}
printf("\n");
}
else
iterate(a, i+1, size, n);
}
}
You can use recursion:
void iterate(int *a, int i, int size, int n)
{
for(a[i] = 0; a[i] < size; a[i]++)
{
if(i == n-1)
DoStuff(a, n); // a is the array of indices of size n
else
iterate(a, i+1, size, n);
}
}
...
// Equivalent to 4 nested for loops
int a[4];
iterate(a, 0, size, 4);
You likely could do this with some recursion.
Here is something I used for a similar problem. It does not use recursion; rather, it uses a vector of indexes.
#include <vector>
template<class T>
class MultiForVar {
std::vector<T> _begin, _end, _vars;
inline int dim(){return _vars.size();}
public:
MultiForVar(std::vector<T> begin, std::vector<T> end) : _begin(begin), _end(end), _vars(_begin)
{
assert(begin.size() == end.size() and "Starting and ending vector<T> not the same size!" );
}
MultiForVar& operator ++()
{
++_vars[dim()-1];
for(int d = dim()-1; d > 0; --d)
{
if( _vars[d] >= _end[d] )
{
_vars[d] = _begin[d];
++_vars[d-1];
}
}
return *this;
}
bool done()
{
/*for(int d = 0; d < dim(); ++d)
if( _vars[d] < _end[d] )
return false;
return true;*/
return (_vars[0] >= _end[0]);
}
T operator[](int d)
{
return _vars.at(d);
}
int numDimensions(){
return dim();
}
std::vector<T>& getRaw(){
return _vars;
}
};
If I understand what you're asking correctly, another way to do it is to use bit-wise operators:
for(int i = 0; i < 1<<size; i++) {
for(int j = 0; j < size; j++) {
if(i & 1<<j) printf("%d ", a[j]);
}
printf("\n");
}
You need something the constructs the powerset of the original set. It's been a while since I've written that, but the psuedocode looks like
Powerset(a, size)
{
if(size == 0) return emptyset
subseta = Powerset(a, size-1) // Powerset of everything except last element
subsetb = appendToAll(a[size-1], subseta) // appends the last element to every set in subseta
return union(subseta, subsetb)
}