Unable to Input the graph - c++

I am solving the problem http://www.spoj.com/problems/SHOP/ in C++ but I am unable to figure out how to input the graph to furhter apply Dijkstra algorithm in it.
Here is the graph format-
4 3
X 1 S 3
4 2 X 4
X 1 D 2
First line indicated the columns & rows of the grid ,"S" & "D" -indicates source and destination respetively Numbers -indicates the time required to pass that block,"X"-indicates the no entry zone.
HOw to convert the following graph in nodes and edges as required by DIjkstra algorithm.I don't know how to convert the map into a graph.

There is no need to convert. Just imagine that you are in some point (i,j). (I assume that you have four moves allowed from each square). Then, you can go to either (i + 1, j), (i, j + 1), (i - 1, j), (i, j - 1) if:
1) That index is inside the table
2) That index is not marked with X
So, you give the position of square S to your Dijkstra algorithm. And each time you add the new set of allowed squares to your data structure. Once your reach the position of D you print it.
Besides, this problem does not seem weighted to me so you can use a simple BFS as well using a queue. But if you want to use Dijkstra and going to different squares has different costs. The you use a priority queue instead of queue.
For example, you can use a set data structure like this:
int dist[][]; // this contains the cost to get to some square
//dist is initialized with a large number
struct node{
int i, j; //location
node(int ii, int jj){
i = ii;
j = jj;
}
bool operator < (node &n)const{ //set in c++ will use this to sort
if(dist[i][j] == dist[n.i][n.j]) return i < n.i || j < n.j; //this is necessary
return dist[i][j] < dist[n.i][n.j];
}
};
set <node> q;
int main(){
//initialized dist with large number
dist[S.i][S.j] = 0; //we start from source
q.push(node(S.i, S.j));
while(true){
//pick the first element in set
//this element has the smallest cost
//update dist using this node if necessary
//for every node that you update remove from q and add it again
//this way the location of that node will be updated in q
//if you see square 'D' you are done and you can print dist[D.i][D.j]
}
return 0;
}

There is no need to convert the matrix into nodes and edges.
You can make structure which contain (row number,column number ,time ) where time will represent how much time taken to reach this coordinate from source. now make a min heap of this structure with key as time. now extract element (initially source will be in min heap with time as 0) from min heap and push the adjacent elements into min heap(only those elements which are not visited and do not contain a X) set visited of extracted element true.Go on like this until extracted element is not destination.

Related

Minimum number of elements required to make two bags of at least k weight?

Suppose you are given a number k and an array of objects having some weight. Now your task is to find the minimum number of objects that you can put in two bags such that each bag weigh at least k.
You can only take the objects as whole no breaking is allowed. Also, if an object is put in one bag it cannot be put into the other bag.
This problem seems simple to me. I have done similar problems when you need to fill just one bag. The idea I use is that you visit each object ask yourself what if I put it in the bag and what if I don't? You do this recursively until your desired weight is reached or you have no more objects. Take minimum when calling your recursive function.
However, I am not able to understand how to keep track of all the objects used up in bag 1 so that I don't include in bag 2.
Few Test cases
Desired weight (k) = 4
Number of objects (N) = 1
[10]
Output: -1 (Not possible)
Desired weight (k) = 2
Number of objects (N) = 3
[2,2,2]
Output: 2
I will focus on what you point out as your actual core problem, how to keep track of objects you used in one bag, the other bag or not at all.
Make a list (array, vector, ... whatever container you prefer) and note for each of the objects where you used it - or not.
index
value
meaning
0
0
not used
1
0
not used
2
0
not used
3
1
used in one bag
4
2
used in other bag
From your question it is not clear to me whether all objects have the same weight or different weights given in the input. If the weights are different, then you most likely already have a container for keeping track of the weight of each object. Modifying that container or using a second, very similar one will help you to also store the "used where" information.
I am intentionally not going into detail, because of
How do I ask and answer homework questions?
I don't know if this answers your question or not, but still...
You can do one thing: Initially make two empty arrays, say Bag_1 and Bag_2. As you recurse through all elements one by one, pop that element out of the array and append it to Bag_1 or Bag_2 whichever gives you the optimal solution. If the process is to be done multiple times, then creating a copy of the original array might help, if the length of the array is reasonable.
Here is the pseudo code for the program without dynamic programing.
sort(a, a+n); // Sort the array of objects having weight
int sum = a[n-1], count = -1; //Initialise sum and count
unordered_set<int>log; // Create an unordered set to store logs (Unordered set will not add repetitive values in the log thus decreasing time complexity)
log.insert(a[n-1]); // insert last element int log initially
for(int i = n-2; i >=0; i--) {
sum += a[i]; //increment the sum
unordered_set<int>temp; //Create a temporary log that will be mapped to main log at the end.
temp.insert(a[i]); //insert the sum to temp log
for (auto it = log.begin(); it != log.end(); ++it) { //loop over all logs seen till now
temp.insert(*it + a[i]); // Add current sum to each of them and insert it to temp log thus creating all possible combinations.
if((a[i] + *it >= k) && (sum - a[i] - *it >= k)) { //Condition to check if bags have been filled with at least k weight.
count = n-i; // update the current count. This will be the ans.
break;
}
if(a[i] >= k && sum - a[i] >= k) {
count = n-i;
break;
}
}
if(count != -1) { //Condition to check if it's not possible to make such a combination.
break;
}
log.insert(temp.begin(), temp.end()); // add all temp to main log.
}
cout << count << endl; //print ans.

Please tell me the efficient algorithm of Range Mex Query

I have a question about this problem.
Question
You are given a sequence a[0], a 1],..., a[N-1], and set of range (l[i], r[i]) (0 <= i <= Q - 1).
Calculate mex(a[l[i]], a[l[i] + 1],..., a[r[i] - 1]) for all (l[i], r[i]).
The function mex is minimum excluded value.
Wikipedia Page of mex function
You can assume that N <= 100000, Q <= 100000, and a[i] <= 100000.
O(N * (r[i] - l[i]) log(r[i] - l[i]) ) algorithm is obvious, but it is not efficient.
My Current Approach
#include <bits/stdc++.h>
using namespace std;
int N, Q, a[100009], l, r;
int main() {
cin >> N >> Q;
for(int i = 0; i < N; i++) cin >> a[i];
for(int i = 0; i < Q; i++) {
cin >> l >> r;
set<int> s;
for(int j = l; j < r; j++) s.insert(a[i]);
int ret = 0;
while(s.count(ret)) ret++;
cout << ret << endl;
}
return 0;
}
Please tell me how to solve.
EDIT: O(N^2) is slow. Please tell me more fast algorithm.
Here's an O((Q + N) log N) solution:
Let's iterate over all positions in the array from left to right and store the last occurrences for each value in a segment tree (the segment tree should store the minimum in each node).
After adding the i-th number, we can answer all queries with the right border equal to i.
The answer is the smallest value x such that last[x] < l. We can find by going down the segment tree starting from the root (if the minimum in the left child is smaller than l, we go there. Otherwise, we go to the right child).
That's it.
Here is some pseudocode:
tree = new SegmentTree() // A minimum segment tree with -1 in each position
for i = 0 .. n - 1
tree.put(a[i], i)
for all queries with r = i
ans for this query = tree.findFirstSmaller(l)
The find smaller function goes like this:
int findFirstSmaller(node, value)
if node.isLeaf()
return node.position()
if node.leftChild.minimum < value
return findFirstSmaller(node.leftChild, value)
return findFirstSmaller(node.rightChild)
This solution is rather easy to code (all you need is a point update and the findFisrtSmaller function shown above and I'm sure that it's fast enough for the given constraints.
Let's process both our queries and our elements in a left-to-right manner, something like
for (int i = 0; i < N; ++i) {
// 1. Add a[i] to all internal data structures
// 2. Calculate answers for all queries q such that r[q] == i
}
Here we have O(N) iterations of this loop and we want to do both update of the data structure and query the answer for suffix of currently processed part in o(N) time.
Let's use the array contains[i][j] which has 1 if suffix starting at the position i contains number j and 0 otherwise. Consider also that we have calculated prefix sums for each contains[i] separately. In this case we could answer each particular suffix query in O(log N) time using binary search: we should just find the first zero in the corresponding contains[l[i]] array which is exactly the first position where the partial sum is equal to index, and not to index + 1. Unfortunately, such arrays would take O(N^2) space and need O(N^2) time for each update.
So, we have to optimize. Let's build a 2-dimensional range tree with "sum query" and "assignment" range operations. In such tree we can query sum on any sub-rectangle and assign the same value to all the elements of any sub-rectangle in O(log^2 N) time, which allows us to do the update in O(log^2 N) time and queries in O(log^3 N) time, giving the time complexity O(Nlog^2 N + Qlog^3 N). The space complexity O((N + Q)log^2 N) (and the same time for initialization of the arrays) is achieved using lazy initialization.
UP: Let's revise how the query works in range trees with "sum". For 1-dimensional tree (to not make this answer too long), it's something like this:
class Tree
{
int l, r; // begin and end of the interval represented by this vertex
int sum; // already calculated sum
int overriden; // value of override or special constant
Tree *left, *right; // pointers to children
}
// returns sum of the part of this subtree that lies between from and to
int Tree::get(int from, int to)
{
if (from > r || to < l) // no intersection
{
return 0;
}
if (l <= from && to <= r) // whole subtree lies within the interval
{
return sum;
}
if (overriden != NO_OVERRIDE) // should push override to children
{
left->overriden = right->overriden = overriden;
left->sum = right->sum = (r - l) / 2 * overriden;
overriden = NO_OVERRIDE;
}
return left->get(from, to) + right->get(from, to); // split to 2 queries
}
Given that in our particular case all queries to the tree are prefix sum queries, from is always equal to 0, so, one of the calls to children always return a trivial answer (0 or already computed sum). So, instead of doing O(log N) queries to the 2-dimensional tree in the binary search algorithm, we could implement an ad-hoc procedure for search, very similar to this get query. It should first get the value of the left child (which takes O(1) since it's already calculated), then check if the node we're looking for is to the left (this sum is less than number of leafs in the left subtree) and go to the left or to the right based on this information. This approach will further optimize the query to O(log^2 N) time (since it's one tree operation now), giving the resulting complexity of O((N + Q)log^2 N)) both time and space.
Not sure this solution is fast enough for both Q and N up to 10^5, but it may probably be further optimized.

C++ creating a graph out of dot coordinates and finding MST

I'm trying to make a program in which the user inputs n dot coordinates, 0 < n <= 100. Supposedly, the dots have to be connected, lets say, with ink in a way that you can get e.g from point A to point X while following the inked line and using the least amount of ink possible.
I thought of using Prim Algorithm or something like that to get the MST but for that I need a graph. In all the webpages I've looked they don't really explain that, they always already have the graph with its edges already in there.
I need help specifically creating a graph in C++ out of a bunch of (x, y) coordinates, like the user inputs:
0 0
4 4
4 0
0 4
Please note I'm just starting with C++ and that I can't use any weird libraries since this would be for a page like CodeForces where you only get to use the native libraries.
(For the ones that are also doing this and are here for help, the correct output for this input would be 12)
To assume a complete graph may be most appropriate as suggested by "Beta".
Following code may creates edges between every pair of two dots from a list of dots in the array dots and returns the number of edges created.
After execute this code, you may be able to apply Prim Algorithm for finding MST.
// Definition of Structure "node" and an array to store inputs
typedef struct node {
int x; // x-cordinate of dot
int y; // y-cordinate of dot
} dots[100];
// Definition of Structure "edge"
typedef struct edge {
int t1; // index of dot in dots[] for an end.
int t2; // index of dot in dots[] for another end.
float weight; // weight (geometric distance between two ends)
} lines[];
// Function to create edges of complete graph from an array of nodes.
// Argument: number of nodes stored in the array dots.
// ReturnValue: number of edges created.
// Assumption: the array lines is large enough to store all edges of complete graph
int createCompleteGraph(int numberOfNodes){
int i,j,k,x-diff,y-diff;
k=0; // k is index of array lines
for (i=0; i<numberOfNodes-1; i++) {// index of a node at one end
for (j=i+1; j<numberOfNodes; j++) {// index of a node at another end
lines[k].t1 = i;
lines[k].t2 = j;
x-diff = dots[i].x - dots[j].x;
y-diff = dots[i].y - dots[j].y;
lines[k].weight = sqrt(x-diff * x-diff + y-diff * y-diff) // calculate geometric distance
k++;
}
}
return k;
}

finding a element in a matrix with the minimum cost starting from one point

I have n*n matrix and I want to find the element from the matrix that has the minimum cost, the cost of a node meaning cost = Manhattandistance(startingnode,node) + costof(node) where starting node is a node in which perspective I am searching!
I did it just with 4 for loops and it works but I want to optimize it and I did something like a bfs: I used a queue and added first the starting node, after that in a while loop I pop ed the node from the queue and added to the queue all the elements around that node with the Manhatttan 1. I do this while the distance of the node that I just popped from the queue + the minimum price from the whole matrix (which I know from the start) is less than the minimum price that I have just found ( I compare the price of the node I just popped with min) if it's bigger I stop searching because the minimum node I found is the lowest possible value. The problem is this algorithm is to slow possibly because I use a std::queue? and it works in more time than the 4 for loops version. (I also used a flags matrix to see if the element I am inspecting when I add to the queue has been already added). The most time consuming block of code is the part I expand the node don't know why I just inspect if the element is valid I mean it's coordinates are less than n and bigger than 0 if ok I add the element to the queue!
I want to know how can I improve this or if it's another way to do it! Hope I was explicit enough.
this is the part of code that takes to long:
if((p1.dist + 1 + Pmin) < pretmincomp || (p1.dist + 1 + Pmin) < pretres){
std::vector<PAIR> vec;
PAIR pa;
int p1a=p1.a,p1b = p1.b,p1d = p1.dist;
if(isok(p1a+1,p1b,n)){
pa.a = p1a + 1;
pa.b = p1b;
pa.dist = p1d + 1;
vec.push_back(pa);
}
if(isok(p1a-1,p1b,n)){
pa.a = p1a - 1;
pa.b = p1b;
pa.dist = p1d + 1;
vec.push_back(pa);
}
if(isok(p1a,p1b+1,n)){
pa.a = p1a;
pa.b = p1b + 1;
pa.dist = p1d + 1;
vec.push_back(pa);
}
if(isok(p1a,p1b -1 ,n)){
pa.a = p1.a;
pa.b = p1.b - 1;
pa.dist = p1d + 1;
vec.push_back(pa);
}
for(std::vector<PAIR>::iterator it = vec.begin();
it!=vec.end(); it++){
if(flags[(*it).a][(*it).b] !=1){
devazut.push(*it);
flags[(*it).a][(*it).b] = 1;
}
}
You are dealing with a shortest path problem, which can be efficiently solved with BFS (if the graph is unweighted) or A* algorithm - if you have some "knowledge" on the graph and can estimate how much it will "cost" you to find a target from each node.
Your solution is very similar to BFS with one difference - BFS also maintains a visited set - of all the nodes you have already visited. The idea of this visited set is that you don't need to revisit a node that was already visited, because any path through it will be not shorter then the shortest path you will find during the first visit of this node.
Note that without the visited set - each node is revisited a lot of times, which makes the algorithm very inefficient.
Pseudo code for BFS (with visited set):
BFS(start):
q <- new queue
q.push(pair(start,0)) //0 indicates the distance from the start
visited <- new set
visited.add(start)
while (not q.isEmpty()):
curr <- q.pop()
if (curr.first is target):
return curr.second //the distance is indicated in the second element
for each neighbor of curr.first:
if (not set.contains(neighbor)): //add the element only if it is not in the set
q.push(pair(neighbor,curr.second+1)) //add the new element to queue
//and also add it to the visited set, so it won't be re-added to the queue.
visited.add(neighbot)
//when here - no solution was found
return infinity //exhausted all vertices and there is no path to a target

Top 10 Frequencies in a Hash Table with Linked Lists

The code below will print me the highest frequency it can find in my hash table (of which is a bunch of linked lists) 10 times. I need my code to print the top 10 frequencies in my hash table. I do not know how to do this (code examples would be great, plain english logic/pseudocode is just as great).
I create a temporary hashing list called 'tmp' which is pointing to my hash table 'hashtable'
A while loop then goes through the list and looks for the highest frequency, which is an int 'tmp->freq'
The loop will continue this process of duplicating the highest frequency it finds with the variable 'topfreq' until it reaches the end of the linked lists on the the hash table.
My 'node' is a struct comprising of the variables 'freq' (int) and 'word' (128 char). When the loop has nothing else to search for it prints these two values on screen.
The problem is, I can't wrap my head around figuring out how to find the next lowest number from the number I've just found (and this can include another node with the same freq value, so I have to check that the word is not the same too).
void toptenwords()
{
int topfreq = 0;
int minfreq = 0;
char topword[SIZEOFWORD];
for(int p = 0; p < 10; p++) // We need the top 10 frequencies... so we do this 10 times
{
for(int m = 0; m < HASHTABLESIZE; m++) // Go through the entire hast table
{
node* tmp;
tmp = hashtable[m];
while(tmp != NULL) // Walk through the entire linked list
{
if(tmp->freq > topfreq) // If the freqency on hand is larger that the one found, store...
{
topfreq = tmp->freq;
strcpy(topword, tmp->word);
}
tmp = tmp->next;
}
}
cout << topfreq << "\t" << topword << endl;
}
}
Any and all help would be GREATLY appreciated :)
Keep an array of 10 node pointers, and insert each node into the array, maintaining the array in sorted order. The eleventh node in the array is overwritten on each iteration and contains junk.
void toptenwords()
{
int topfreq = 0;
int minfreq = 0;
node *topwords[11];
int current_topwords = 0;
for(int m = 0; m < HASHTABLESIZE; m++) // Go through the entire hast table
{
node* tmp;
tmp = hashtable[m];
while(tmp != NULL) // Walk through the entire linked list
{
topwords[current_topwords] = tmp;
current_topwords++;
for(int i = current_topwords - 1; i > 0; i--)
{
if(topwords[i]->freq > topwords[i - 1]->freq)
{
node *temp = topwords[i - 1];
topwords[i - 1] = topwords[i];
topwords[i] = temp;
}
else break;
}
if(current_topwords > 10) current_topwords = 10;
tmp = tmp->next;
}
}
}
I would maintain a set of words already used and change the inner-most if condition to test for frequency greater than previous top frequency AND tmp->word not in list of words already used.
When iterating over the hash table (and then over each linked list contained therein) keep a self balancing binary tree (std::set) as a "result" list. As you come across each frequency, insert it into the list, then truncate the list if it has more than 10 entries. When you finish, you'll have a set (sorted list) of the top ten frequencies, which you can manipulate as you desire.
There may be perform gains to be had by using sets instead of linked lists in the hash table itself, but you can work that out for yourself.
Step 1 (Inefficient):
Move the vector into a sorted container via insertion sort, but insert into a container (e.g. linkedlist or vector) of size 10, and drop any elements that fall off the bottom of the list.
Step 2 (Efficient):
Same as step 1, but keep track of the size of the item at the bottom of the list, and skip the insertion step entirely if the current item is too small.
Suppose there are n words in total, and we need the most-frequent k words (here, k = 10).
If n is much larger than k, the most efficient way I know of is to maintain a min-heap (i.e. the top element has the minimum frequency of all elements in the heap). On each iteration, you insert the next frequency into the heap, and if the heap now contains k+1 elements, you remove the smallest. This way, the heap is maintained at a size of k elements throughout, containing at any time the k highest-frequency elements seen so far. At the end of processing, read out the k highest-frequency elements in increasing order.
Time complexity: For each of n words, we do two things: insert into a heap of size at most k, and remove the minimum element. Each operation costs O(log k) time, so the entire loop takes O(nlog k) time. Finally, we read out the k elements from a heap of size at most k, taking O(klog k) time, for a total time of O((n+k)log k). Since we know that k < n, O(klog k) is at worst O(nlog k), so this can be simplified to just O(nlog k).
A hash table containing linked lists of words seems like a peculiar data structure to use if the goal is to accumulate are word frequencies.
Nonetheless, the efficient way to get the ten highest frequency nodes is to insert each into a priority queue/heap, such as the Fibonacci heap, which has O(1) insertion time and O(n) deletion time. Assuming that iteration over the hash table table is fast, this method has a runtime which is O(n×O(1) + 10×O(n)) ≡ O(n).
The absolute fastest way to do this would be to use a SoftHeap. Using a SoftHeap, you can find the top 10 items in O(n) time whereas every other solution posted here would take O(n lg n) time.
http://en.wikipedia.org/wiki/Soft_heap
This wikipedia article shows how to find the median in O(n) time using a softheap, and the top 10 is simply a subset of the median problem. You could then sort the items that were in the top 10 if you needed them in order, and since you're always at most sorting 10 items, it's still O(n) time.