Dijkstra' algorithm- vertex as coordinate - c++

I went through Dijkstra for shortest path algorithm,while i was practicing i encountered a question in which vertex is not a single number(say 1,2,3...and so)but it was a pair more specifically given as (x,y)coordinates.I have never done such type of question nor i have seen them.Can you please help me out how to approach for such kind of question.O(V^2) is heartily welcome

Map the coordinates to integer vertices using a hashmap. Now you have a graph with nodes as single numbers. Apply dijkstra's algorithm. Time complexity : O(V) for converting to integer vertices. O(V^2) for running dijkstra's algorithm. Therefore O(V^2) total complexity.
Pseudo code:
int cntr = 0;
for(Edge e : graph){
int from = e.from;
int to= e.to;
if(!map.contains(from)){
map.put(from, cntr++);
}
if(!map.contains(to)){
map.put(to, cntr++);
}
}

Each vertex would still have an id (which you could assign, if not given). The Cartesian coordinates are just additional attributes of the vertex, which could be used to compute distances between connected vertices. (sqrt(delta_x^2 + delta_y^2))

Related

Hashing pairs of integers to array indices?

I have a set of sequential, 0-based integers representing vertex indices in a mesh.
Every vertex is connected to at least 2 other vertices, to form edges of the mesh.
Edges are represented by pairs of vertices. So, for example, (0, 2) might be one edge between vertex 0 and 2.
Currently, in order to quickly lookup edges in my mesh, I store my Edge class in a std::unordered_map, and generate hashes as follows:
//sorted so (0, 2) and (2, 0) will return same hash
__int64 GetEdgeHash (int vertex1, int vertex2)
{
return (__int64)min(vertex1, vertex2) * INT_MAX + max(vertex1, vertex2);
}
However, an unordered_map has enough overhead during creation and lookup that it has a noticeable performance impact elsewhere in my code. I'm wondering if there's a way to hash pairs of integer such that each pair corresponds to some index an array whose size is <= numVertices * 2 (since the number of edges in a mesh could never exceed that value). If that were possible, I could just use a normal std::vector to store my edges and processing them would be much faster.
Obviously that's not currently possible since my hash function will return values anywhere from 0 to 4611686016279904256.
A naive approach like:
int GetEdgeHash (int vertex1, int vertex2)
{
return vertex1 + vertex;
}
would satisfy the array size limitation, but obviously results in many collisions.
Is there another way to achieve the same goal?
A very simple solution could be based on your initial approach, however not using INT_MAX, but the number of existing vertices:
uint64_t numberOfVertices;
uint64_t index(uint32_t vertex1, uint32_t vertex2)
{
return vertex1 * numberOfVertices + vertex2;
}
This algorithm is collision free, but requires a vector size of the square of numberOfVertices; as is, though, is only applicable if you have a fix (or at least, a maximum) number of vertices.
If the number of vertices might increase beyond the maximum, you could e. g. duplicate the maximum each time it is exceeded, which would, however, require to re-"hash" all your nodes in the vector, i. e. this is an expensive operation and should occur as rarely as possible (duplication of maximum might already make this rare enough...).

create pairs of vertices using adjacency list in linear time

I have n number of vertices numbered 1...n and want to pair every vertex with all other vertices. That would result in n*(n-1)/2 number of edges. Each vertex has some strength.The difference between the strength of two vertices is the weight of the edge.I need to get the total weight. Using two loops I can do this in O(n^2) time. But I want to reduce the time.I can use adjacency list and using that create a graph of n*(n-1)/2 edges but how will I create the adjacency list without using two loops. The input takes only the number of vertices and the strength of each vertex.
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
int w=abs((strength[i]-strength[j]));
sum+=w;
}
this is what i did earlier.I need a better way to do this.
If there are O(N*N) edges, then you can't list them all in linear time.
However, if indeed all you need is to compute the sum, here's a solution in O(N*log(N)). You can kind of improve the solution by using instead O(N) sorting algorithm, such as radix sort.
#include <algorithm>
#include <cstdint>
// ...
std::sort(strength, strength+n);
uint64_t sum = 0;
int64_t runSum = strength[0];
for(int i=1; i<n; i++) {
sum += int64_t(i)*strength[i] - runSum;
runSum += strength[i];
}
// Now "sum" contains the sum of weigths over all edges
To explain the algorithm:
The idea is to avoid summing over all edges explicitly (requiring O(N*N)), but rather to add sums of several weights at once. Consider the last vertex n-1 and the average A[n-1] = (strength[0] + strength[1] + ... + strength[n-2])/(n-1): obviously we could add (strength[n-1] - A[n-1]) * (n-1), i.e. n-1 weights at once, if the weights were all larger than strength[n-1], or all smaller than it. However, due to abs operation, we would have to add different amounts depending on whether the strength of the other vertex is larger or smaller than the strength of the current vertex. So one solution is to sort the strengths first, so to ensure that each next strength is greater or equal to the previous.

C++ : Storing weight for larger Graph

I was solving some question on graph. It requires to store weight for N Nodes(N<=50000). I cant use matrix to store weight of graph(as 50000x50000 can't be allocated). Do you know any other way? Thanks.
My preferred way of storing not too dense graphs is using adjacency lists.
The downside using adjacency lists is however that you can't directly check if node i is connected to node j. Instead you traverse all neighbors of node i (in which j would eventually show up if it is connected with node i). Also it's not practical to remove edges. I use it when doing breadth-first or depth-first searches on a graph, since one is only interested in the set of neighbors and not whether two specific nodes are connected.
In summary:
Takes only as much memory as you have edges (which is what you wanted) but at least as much memory as you have nodes.
Easy to traverse egdes for any node, i.e. always constant time per neighbor
To check whether two nodes i and j are connected you need to traverse the whole neighborhoodlist of node i or j. Which is bad if one node is connected to almost all other nodes and cheap if its connected to a few
Removing edges is also expensive for large neighborhoods (at worst linear time in the number of neighbors of a node) and cheap for small neighborhoods.
Inserting edges is very cheap (constant time)
To give you an example (first with all weights 1)
using Graph = std::vector<std::vector<int>>;
now you can create a graph with n nodes with:
Graph mygraph(n);
And if you want to connect node i and j just do
mygraph[i].push_back(j);
mygraph[j].push_back(i);
And to traverse all edges of some node, you can simply do
for (int neighbor : mygraph[i]) {
std::cout << i << " is connected with " << neighbor << std::endl;
}
And now for the harder problem with general weights:
using Graph = std::vector<std::vector<std::pair<int, double>>>;
Graph myWeightedgraph(n);
Now you can insert edges very easily
double weight = 123.32424;
myWeightedgraph[i].push_back({j, w});
myWeightedgraph[j].push_back({i, w});
And for traversal:
for (auto& neighbor : myWeightedgraph[i]) {
std::cout << i << " is connected with " << neighbor.first << " with weight " << neighbor.second << std::endl;
}
If two nodes can't have multiple edges between them:
First think of some system how to give each existing edge an unique number.
Eg. for N nodes and node numbers netween 0 and N-1, a edge between node A and node B could simply have A*N+B (eg. in an uint64_t variable)
Then make a std::map of edges, with the calculated number as key and the weight as value. Most operations there have logarithmic time, which is not as good than the 2D array but still good, and you need much less memory.
There are generally two ways to represent graphs. As you stated, the first one is to use an adjacency matrix. The pros are that you can easily see if two nodes i and j are connected. The downside is the space complexity (O(V²) where V is the number of vertices).
The other one is the adjacency list: for each vertex, you store an adjacency list that contains every edge coming out of that vertex. Obviously, the spatial complexity is O(V + E) where V is the number of vertices and E the number of edges.
Note that you can store the edges in adjacency maps instead of lists. Let's say you give each edge a unique integer key. If your graph is sparse, an std::unordered_map would fit well since collisions odds will be low. This grants you on average O(1) lookup and insertion complexity for a given edge.
If your graph can have a huge number of edges, then just use a regular std::map which relies on red black trees. You'll then have a logarithmic complexity for both inserting or looking up a node.
Here is some sample code:
struct Edge {
int weight;
int start, end;
}
struct Vertex {
int key;
std::unordered_map<int, Edge> adjacency_map;
}
struct Graph {
std::vector<Edge> edges;
}
You can't allocate an array with size of orders 10^9 as a static memory. You should be using malloc instead. Better still, you can use adjacency list to store the graph.

Find distance from a node to the one farthest from it BOOST

I need to fin the distance from all nodes to the node farthest from it in the minimum spanning tree. I have done this so far but I got no clue as to find the longest distance from a node.
#include<iostream>
#include<boost/config.hpp>
#include<boost/graph/adjacency_list.hpp>
#include<boost/graph/kruskal_min_spanning_tree.hpp>
#include<boost/graph/prim_minimum_spanning_tree.hpp>
using namespace std;
using namespace boost;
int main()
{
typedef adjacency_list< vecS, vecS, undirectedS, property <vertex_distance_t,int>, property< edge_weight_t, int> > Graph;
int test=0,m,a,b,c,w,d,i,no_v,no_e,arr_w[100],arr_d[100];
cin>>test;
m=0;
while(m!=test)
{
cin>>no_v>>no_e;
Graph g(no_v);
property_map <Graph, edge_weight_t>:: type weightMap=get(edge_weight,g);
bool bol;
graph_traits<Graph>::edge_descriptor ed;
for(i=0;i<no_e;i++)
{
cin>>a>>b>>c;
tie(ed,bol)=add_edge(a,b,g);
weightMap[ed]=c;
}
property_map<Graph,edge_weight_t>::type weightM=get(edge_weight,g);
property_map<Graph,vertex_distance_t>::type distanceMap=get(vertex_distance,g);
property_map<Graph,vertex_index_t>::type indexMap=get(vertex_index,g);
vector< graph_traits<Graph>::edge_descriptor> spanning_tree;
kruskal_minimum_spanning_tree(g,back_inserter(spanning_tree));
vector<graph_traits<Graph>::vector_descriptor>p(no_v);
prim_minimum_spanning_tree(g,0,&p[0],distancemap,weightMap,indexMap,default_dijkstra_visitor());
w=0;
for(vector<graph_traits<Graph>::edge_descriptor>::iterator eb=spanning_tree.begin();eb!=spanning_tree.end();++eb) //spanning tree weight
{
w=w+weightM[*eb];
}
arr_w[m]=w;
d=0;
graph_traits<Graph>::vertex_iterator vb,ve;
for(tie(vb,ve)=vertices(g),.
arr_d[m]=d;
m++;
}
for( i=0;i<test;i++)
{
cout<<arr_w[i]<<endl;
}
return 0;
}
If i have a spanning tree with nodes 1 2 3 4 I need to find longest distance from 1 2 3 4 in the spanning tree(and the longest distance can comprise of many edges not only one).
I'll not give you exact code how to do this but I'll give you and idea how to do this.
First, result of MST (minimum spanning tree) is so called tree. Think about the definition. One can say it is a graph where exists path from every node to every other nodes and there are no cycles. Alternatively you can say that given graph is a tree iff exists exactly one path from vertex u to v for every u and v.
According to the definition you can define following
function DFS_Farthest (Vertex u, Vertices P)
begin
define farthest is 0
define P0 as empty set
add u to P
foreach v from neighbours of u and v is not in P do
begin
( len, Ps ) = DFS_Farthest(v, P)
if L(u, v) + len > farthest then
begin
P0 is Ps union P
farthest is len + L(u, v)
end
end
return (farthest, P0)
end
Then you'll for every vertex v in graph call DFS_Farthest(v, empty set) and it'll give you (farthest, P) where farthest is distance of the farthest node and P is set of vertices from which you can reconstruct the path from v to farthest vertex.
So now to describe what is it doing. First the signature. First parameter is from what vertex you want to know farthest one. Second parameter is a set of banned vertices. So it says "Hey, give me the longest path from v to farthest vertex so the vertices from P are not in that path".
Next there is this foreach thing. There you are looking for farthest vertices from current vertex without visiting vertices already in P (current vertex is already there). When you find path longer then currently found not it to farthest and P0. Note that L(u, v) is length of the edge {u, v}.
At the end you'll return those length and banned vertices (this is the path to the farthest vertex).
This is just simple DFS (depth first search) algorithm where you remember already visited vertices.
Now about time complexity. Suppose you can get neighbours of given vertex in O(1) (depends on data structure you have). Function visits every vertex exactly once. So it is at least O(N). To know farthest vertex from every vertex you have to call this function for every vertex. This gives you time complexity of this solution of your's problem at least O(n^2).
My guess is that better solution might be done using dynamic programming but this is just a guess. Generally finding longest path in graph is NP-hard problem. This makes me suspicious that there might not me any significantly better solution. But it's another guess.

What is the best standard data structure to build a Graph?

at first i am a beginner at c++ and i am self learning it, so please be quite simple in answers ...
i need to program a graph that contains nodes each node has id and list of edges each edge has the other node id and the distance
what i am looking for is what should i use to build this graph considering that i wants to use dijkstra algorithm to get the shortest path form one point to the other ... so searching performance should be the most important i think !!
i have searched a lot and i am so confused now
thank you in advance for the help
You can define an Edge structure like
struct Edge
{
int destination;
int weight;
};
And create a graph as
vector<vector<Edge> > graph;
Then to access all the edges coming from the vertex u, you write something like
for( int i = 0; i < graph[u].size(); ++i ) {
Edge edge = graph[u][i];
// here edge.destination and edge.weight give you some details.
}
You can dynamically add new edges, for example an edge from 3rd vertex to 7th with a weight of 8:
Edge newEdge;
newEdge.destination = 7;
newEdge.weight = 8;
graph[3].push_back( newEdge );
etc.
For undirected graphs you should not forget to add the symmetric edge, of course.
This should do ok.
Edit
The choice of base containers (std::vector, std::list, std::map) depends on the use case, e.g. what are you doing with the graph more often: add/remove vertices/edges, just traversing. Once your graph is created, either std::list or std::vector is equally good for Dijkstra, std::vector being a bit faster thanks to sequential access pattern of the relaxation stage.
Use unordered_map<int,vector<int>> to represent adjacency list if you have huge number of vertexes. If you're planning on implementing a small scale graph, then go with array of vectors. Eg: vector<int> v[20];
a graph that contains nodes each node has id and list of edges each edge has the other node id and the distance
If we consider each node id as an index. We can draw an nxn matrix of the edges as follows.
This can help you draw the graph with edges.
[0][1][2][3]
[0] | 1 0 0 0|
[1] | 0 0 1 0|
[2] | 1 0 0 1|
[3] | 0 0 1 0|
So, a 2D array is a good representation of matrix.
int maxtrix[4][4] = new int[4][4];
I personally would use a std::map<Node*, std::set<Node*> >. This is extremely useful because each time you are at a node, you can quickly find out which nodes that node is connected to. It is also really easy to iterate over all the nodes if you need to. If you need to put weights on the edges, you could use std::map<Node*, std::set< std::pair<int, Node*> > >. This will give much better performance than using vectors, especially for large graphs.