I found this code online for a adjacency list that uses a vector of a pair of ints. I'm trying to understand the code and can't quite figure out what this specific line is doing in the addEdge function: adj[u].push_back(make_pair(v, wt)); . adj is the name of the vector. I get confused in the print method. When it prints, i don't understand where the source node is being stored. I get that the destination node and weight are being stored as a pair, but where does the source node int get saved? I tried experimenting with the code to understand what was going on, as seen with this line in the print function: cout << "Index: " << u << " "; but it didn't help. Here is the code:
void addEdge(vector <pair<int, int> > adj[], int u,
int v, int wt)
{
adj[u].push_back(make_pair(v, wt));
adj[v].push_back(make_pair(u, wt));
}
// Print adjacency list representaion ot graph
void printGraph(vector<pair<int,int> > adj[], int V)
{
int v, w;
for (int u = 0; u < V; u++)
{
cout << "Node " << u << " makes an edge with \n";
for (auto it = adj[u].begin(); it!=adj[u].end(); it++)
{
cout << "Index: " << u << " ";
v = it->first;
w = it->second;
cout << "\tNode " << v << " with edge weight ="
<< w << "\n";
}
cout << "\n";
}
}
// Driver code
int main()
{
int V = 5;
vector<pair<int, int> > adj[V];
addEdge(adj, 0, 1, 10);
addEdge(adj, 0, 4, 20);
addEdge(adj, 1, 2, 30);
addEdge(adj, 0, 3, 40);
addEdge(adj, 1, 4, 50);
addEdge(adj, 2, 3, 60);
addEdge(adj, 3, 4, 70);
addEdge(adj, 0, 2, 10);
printGraph(adj, V);
}
For reference, this is the output for the first two nodes:
Node 0 makes an edge with
Index: 0 Node 1 with edge weight =10
Index: 0 Node 4 with edge weight =20
Index: 0 Node 3 with edge weight =40
Index: 0 Node 2 with edge weight =10
Node 1 makes an edge with
Index: 1 Node 0 with edge weight =10
Index: 1 Node 2 with edge weight =30
Index: 1 Node 4 with edge weight =50
From your code adj is an array of vectors. So adj[u] is a vector and .push_back stores the node in that particular vector. push_back(), begin() and end() are methods in the vector. begin() returns an iterator to the first element (in your case it is a pair) so it is an iterator to a pair and you access the elements using it->first and it-second and you go to the next element (iterate) using it++
Related
I have this exercise:
Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.
For example, input [3, 4, -1, 1] should give 2 and input [1, 2, 0] should give 3.
You can modify the input array in-place.
My implementation:
template <typename In_It>
int missingPositiveInt(In_It first, In_It last){
first = std::find_if( first, last, [](int x){return x > 0;} );
if(first == last || *first > 1)
return 1;
for( auto next = first; (++next != last) && ( !(*next - *first > 1) ); )
++first;
return *first + 1;
}
int main(){
std::vector<int> v{5, 2, -1, 7, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {2, -1, 1, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {5, 2, -1, 7, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {3, 4, -1, 1};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {1, 2, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
std::cout << '\n';
}
The output:
1
3
1
2
3
The program works just fine but I use the algorithm std::find_if to find the first positive value in the sequence (sorted sequence) and that algorithm does a linear search.
As long as the input sequence is already sorted I want to use some binary search algorithm to speed the process.
I tried using std::binary_search but it requires an argument to be searched for. What I need is to get a version that takes a unary predicate and applies a binary search or any other faster algorithm to find the lowest positive value in the sequence so I can write:
auto it = binary_search(first, last, [](int x){ return x > 0; });
Is it possible? Is my code fine or I need to modify it. So any suggestion, hint is highly appreciated.
Yes, std::partition_point does exactly what you want.
Partial solution based on #numzero's answer. This doesn't handle negative numbers or zero in the array but you can handle that by linearly preprocessing the array to remove them beforehand. It just marks each index as "found" by negating it, then later looks for the first non negative value and thats the one. Even though its a partial solution it shows the core algorithm.
#include <iostream>
using namespace std;
int main() {
int arr[] = {1, 4, 6, 7, 2, 7, 7, 8, 3};
int arrSize = sizeof(arr)/sizeof(int);
for(int i=0; i<arrSize; ++i)
{
int val = abs(arr[i]);
if(val > 0 && val-1 < arrSize)
{
if (arr[val-1]>0)
{
arr[val-1] = -arr[val-1];
}
}
}
for(int i=0; i<arrSize; ++i)
{
if(arr[i] > 0)
{
std::cout << "Smallest is " << (i+1) << std::endl;
return 0;
}
}
std::cout << "Nothing found!" << std::endl;
// your code goes here
return 0;
}
I have a doubt in a line given below of this code:
cout<<"("<<c<<","<<(*i).get_vertex()<<") value of this pair : "<<(*i).get_weight()<<", ";
How this get_vertex and get_weight work without the help of class edge object. The code compiled successfully and it's working too but I can't figure out how the above line is working.
Output of the code is:
Pairs for 0 are -> (0,1) value of this pair : 2, (0,2) value of this pair : 3, (0,3) value of this pair : 4,
Pairs for 1 are -> (1,2) value of this pair : 5, (1,0) value of this pair : 2,
Pairs for 2 are -> (2,3) value of this pair : 8, (2,1) value of this pair : 5,
Pairs for 3 are -> (3,0) value of this pair : 4, (3,2) value of this pair : 8,
Code is given below:
#include<bits/stdc++.h>
using namespace std;
class edge{
int weight,vertex;
public:
edge(int w , int v){
weight = w;
vertex = v;
}
int get_weight()const{
return weight;
}
int get_vertex()const{
return vertex;
}
};
int main(){
int n = 4;
int c = 0;
vector<list<edge>>adj(n) ;
adj[0].push_back(edge(2,1));
adj[0].push_back(edge(3,2));
adj[0].push_back(edge(4,3));
adj[1].push_back(edge(5,2));
adj[1].push_back(edge(2,0));
adj[2].push_back(edge(8,3));
adj[2].push_back(edge(5,1));
adj[3].push_back(edge(4,0));
adj[3].push_back(edge(8,2));
vector<list<edge>>:: iterator it ;
for(it=adj.begin();it!=adj.end();it++){
cout<<" Pairs for "<<c<<" are -> ";
list<edge>li = *it;
list<edge>::iterator i;
for(i=li.begin();i!=li.end();i++){
cout<<"("<<c<<","<<(*i).get_vertex()<<") value of this pair : "<<(*i).get_weight()<<", ";
}
cout<<endl;
c++;
}
}
Break it into chunks.
Add whitespace:
cout << "("
<< c
<< ","
<< (*i).get_vertex()
<< ") value of this pair : "
<< (*i).get_weight()
<< ", ";
Does that make more sense?
I'm trying to debug this program to find the number of matching elements that occur at the same index in 2 different vectors. Requirement is to NOT use any loops
Code on online compiler: http://cpp.sh/8rvtj
#include <iostream>
#include <vector>
using namespace std;
int calls=0;
int matchCount(const vector<int>& v1, const vector<int>& v2, int i=0)
{
calls++;
static int smallVecSz=-1;
smallVecSz = (v1.size()<v2.size() ? v1.size() : v2.size());
static int ans=0;
if(i==smallVecSz)
{
cout << "Returning " << ans << endl;
return ans;
}
// if element at index i is same in v1 and v2, add 1 to ans else add 0 to ans
ans += (v1[i]==v2[i] ? 1 : 0);
return ans + matchCount(v1,v2,i+1); // pass optional param index i+1 to advance to next ele
}
int main()
{
vector<int> v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector<int> v2 = {2, 5, 3, 0, 8, 4, 1};
cout << "There are " << matchCount(v1,v2) << " matching numbers at same indexes" << endl;
cout << "Number of Recursion calls: " << calls << endl;
return 0;
}
Here is a sample input:
vector v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector v2 = {2, 5, 3, 0, 8, 4, 1};
Here is a sample output:
Returning 4
There are 32 matching numbers at same indexes
Number of Recursion calls: 8
My program is recursive function is correctly returning the ans 4. But the main program is printing 32.
Oops, a static variable accumulating in a recursive function is a code smell.
Normally, when you use recursion, each call starts with a clean an fresh environment.
In that case, you accumulate the value of each call with its children to find the total.
Alternatively, you can use a static variable which is updated by each call and just used by the top parent.
But here you are mixing both approaches, actually getting a much too high value.
So 2 ways here:
make ans an automatic (non static) variable:
...
smallVecSz = (v1.size()<v2.size() ? v1.size() : v2.size());
int ans=0;
if(i==smallVecSz)
...
keep ans static, and do not accumulate:
...
ans += (v1[i]==v2[i] ? 1 : 0);
matchCount(v1, v2, i+1); // pass optional param index i+1 to advance to next ele
return ans;
...
Of course in that case, you will get wrong results if you call the function more than once because ans will not be reset to 0 (Thanks to #bruno for noticing)
your problem comes from ans being static and the fact you return it when you reach the end of the vector rather than 0 etc
I do not understand too why that function is recursive
a solution with a loop and an other with recursion as you requested in a comment
#include <iostream>
#include <vector>
using namespace std;
int matchCount(const vector<int>& v1, const vector<int>& v2)
{
vector<int>::const_iterator it1;
vector<int>::const_iterator it2;
int result = 0;
for (it1 = v1.begin(), it2 = v2.begin();
(it1 != v1.end()) && (it2 != v2.end());
++it1, ++it2) {
if (*it1 == *it2)
result += 1;
}
return result;
}
int recurMatchCount(const vector<int>& v1, const vector<int>& v2, int i = 0)
{
return ((i == v1.size()) || (i == v2.size()))
? 0
: (((v1[i] == v2[i]) ? 1 : 0)
+ recurMatchCount(v1, v2, i + 1));
}
int main()
{
vector<int> v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector<int> v2 = {2, 5, 3, 0, 8, 4, 1};
cout << "There are " << matchCount(v1,v2) << " matching numbers at same indexes" << endl;
cout << "There are " << recurMatchCount(v1,v2) << " recur matching numbers at same indexes" << endl;
return 0;
}
How do I erase an element one by one in a vector? I want to check the vector using some conditions after a specific element is removed.
I tried it in this way, but it doesn't work. What's wrong? v is already initialized
long long max = maxSubArraySum(v);
long long t = 0;
for(long long i = 0; i < n ; i++){
std::vector<long long> cv;
cv = v;
//cout << "i = " << i << "v = " <<v[i] << '\n';
cv.erase(find(cv.begin(),cv.end(),v[i])); // <—- wrong
// EDIT
// cv.erase(cv.begin()+i); <—- fix.
t = maxSubArraySum(cv);
//cout << "t = " << t << '\n';
if(t > max){
max = t;
//cout << max << '\n';
}
}
// cout << max << '\n';
}
}
For example, v = {1, -2 , 3, -2 ,5 },
I remove first 1, then maxSubArraySum will be for cv = {-2,3,-2,5 } which is 6 for this subarray {3,-2,5}.
Next I remove -2, then maxSubArraySum will be for cv = {1, 3,-2,5} which is 6 for this subarray {3,-2,5}
Next I remove 3, then maxSubArraySum will be for cv = {1, -2,-2,5} which is -2 for this subarray {-2,5}
Next I remove -2, then maxSubArraySum will be for cv = {1, -2, 3, 5} which is 8 for this subarray {3,5}
Next I remove 5, then maxSubArraySum will be for cv = {1, -2,3,-2} which is 4 for this subarray {1,-2,3}
How do I code it in C++?
EDIT :
I got the answer.
My code is was slightly off as it was deleting the first element find found. In case of duplicates, this showed the error.
So I changed it to delete indexes only.
Thank you.
You don't need to use find. Try this:
cv.erase(cv.begin()+i);
This will find the element at the ith position and delete it, using pointer arithmetic.
Declare the vector cv before the for loop (outside) and your problem will be solved. To simplify, use the v directly instead of making a copy
while (!v.empty()) {
v.erase(v.begin());
cout << endl;
long long t = maxSubArraySum(v);
if (t > max) {
max = t;
// cout << max << endl;
}
}
I was trying to save some space by using a hashmap to represent a graph instead of adjacency matrix, I ran the same snippet using adjacency matrix, and everything worked fine, But as soon as I changed the data structure to a hashmap, it ran into in infinite loop, The infinite loop is because of the bsf function defined which returns a boolean value and more specifically the error is in line : if ((!visited[v]) && (rGraph[make_pair(u, v)] > 0)) somehow this if condition is not working fine while I represent the rGraph as a hashmap.
I would also like to know if using a hashmap to represent the graph is a preferred way ?
Here is the attached code:
bool bfs(map<pair<int, int>, int> rGraph, int s, int t, int parent[])
{
// Create a visited array and mark all vertices as not visited
bool visited[V];
memset(visited, 0, sizeof(visited));
// Create a queue, enqueue source vertex and mark source vertex
// as visited
queue <int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;
// Standard BFS Loop
while (!q.empty())
{
int u = q.front();
q.pop();
for (int v=0; v<V; v++)
{
cout << "Value of graph at: " <<u << " , " << v << " : " << rGraph[make_pair(u, v)] << "\n";
//cout << "!visited[v] : " << (!visited[v]) << "rGraph[u][v] : " << rGraph[make_pair(u, v)] << "\n";
cout << "if condition : " << ((!visited[v]) && (rGraph[make_pair(u, v)] > 0)) << "\n";
if ((!visited[v]) && (rGraph[make_pair(u, v)] > 0))
{
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}
// If we reached sink in BFS starting from source, then return
// true, else false
return (visited[t] == true);
}
// Returns tne maximum flow from s to t in the given graph
int fordFulkerson(map<pair<int, int> , int> graph , int s, int t)
{
int u, v;
// Create a residual graph and fill the residual graph with
// given capacities in the original graph as residual capacities
// in residual graph
map<pair<int, int>, int>rGraph; // Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i][j] is 0, then there is not)
for (u = 0; u < V; u++){
for (v = 0; v < V; v++){
rGraph[make_pair(u, v)] = graph[make_pair(u, v)];
}
}
int parent[V]; // This array is filled by BFS and to store path
int max_flow = 0; // There is no flow initially
// Augment the flow while tere is path from source to sink
while (bfs(rGraph, s, t, parent))
{
// Find minimum residual capacity of the edhes along the
// path filled by BFS. Or we can say find the maximum flow
// through the path found.
int path_flow = INT_MAX;
for (v=t; v!=s; v=parent[v])
{
u = parent[v];
path_flow = min(path_flow, int(rGraph[make_pair(u, v)]));
}
// update residual capacities of the edges and reverse edges
// along the path
for (v=t; v != s; v=parent[v])
{
u = parent[v];
rGraph[make_pair(u, v)] -= path_flow;
rGraph[make_pair(u, v)] += path_flow;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow
return max_flow;
}
int main(){
map< pair<int, int>, int > graph;
graph[make_pair(0, 1)] = 16;
graph[make_pair(0, 2)] = 13;
graph[make_pair(1, 2)] = 10;
graph[make_pair(1, 3)] = 12;
graph[make_pair(2, 1)] = 4;
graph[make_pair(2, 4)] = 14;
graph[make_pair(3, 2)] = 9;
graph[make_pair(3, 5)] = 20;
graph[make_pair(4, 3)] = 7;
graph[make_pair(4, 5)] = 4;*/
cout << "The maximum possible flow is " << fordFulkerson(graph, 0, 5) << "\n";
return 0;
}
And the adjacency matrix looks like :
int graph[V][V] = { {0, 16, 13, 0, 0, 0},
{0, 0, 10, 12, 0, 0},
{0, 4, 0, 0, 14, 0},
{0, 0, 9, 0, 0, 20},
{0, 0, 0, 7, 0, 4},
{0, 0, 0, 0, 0, 0}};
First, just by looking at your code - you are not using hashmap - you are using map (read: red-black tree in most implementations). Equivalent of "hashmap" would be unordered_map. However, if you want to save memory - you have chosen the right container (unordered_map may consume more memory than map - unordered_map (hashmap) requires continuous region of memory for buckets: and of course all buckets are never occupied).
And now to problems:
When you do rGraph[make_pair(u, v)] you are potentially creating a new element in your map. Indexing operator returns (see cppreference):
reference to an existing element pointed by the index make_pair(u, v)
if the element pointed by make_pair(u, v) does not exist - it creates a new element under that index and returns you the reference to that new element.
If you want to check whether an element exists in the map / unordered_map you have to use the find method:
auto p = make_pair(u, v)];
auto iter = rGraph.find(p);
if(iter != rGraph.end())
{//element 'rGraph[p]' exists
}
else
{//element 'rGraph[p]' does not exist
}
You can also combine (potentially) inserting new element with checking whether the new element was actually created - this is usually more efficient than two separate insert and find (see cppreference):
auto p = make_pair(u, v)];
auto res = rGraph.insert(make_pair(p,1)); //insert value '1'
if(res.second)
{//new element was inserted
}
else
{//element already existed
}
//here res.first is an iterator pointing to the element rGraph[p] - newly inserted or not
You should use the count or find methods to check existence of items in the map, instead of the operator [] because it constructs a new item if it doesn't exist. So change
rGraph[make_pair(u, v)]>0
with
rGraph.count(make_pair(u, v))>0
Also, I might suggest passing any large object (such as the map) by reference. Also, as mentioned here, you can use "unordered_map" which is a hash table, instead of "map" which is a tree, since you don't need the map to be ordered.