Have someone input an integer N as the number of vertices in the graph.
Assign random weights on each edges ranging from 1 to 10. Not all possible edges
are present though! As in the above example, represented an absent edge by an X.
Return a pair (M,L), with M and L respectively being the matrix and list representation
of the (same) random graph you are generating.
Use non-digit characters as vertex names, to avoid confusion with edge weights.
#include <iostream>
#include <stdlib.h>
using namespace std;
void gen_random_graph(int n)
{
int adj_matrix[n][n];
for(int u = 0; u < n; u++)
{
for (int v = 0; v < n; v++)
{
if(adj_matrix[u][v]==adj_matrix[v][u])
{
adj_matrix[u][v] = rand() % 10 + 1;
cout << adj_matrix[u][v] << endl;
}
}
}
}
int main()
{
int N;
cout << "enter number of vertices" << endl;
cin >> N;
gen_random_graph(N);
return 0;
}
THis is my code so far. Is it generateing the weights ? and what does it mean i have to return a pair?
A graph can be represented as an N x N adjacency matrix (as you have already set up), where the value in matrix[i][j] corresponds to the weight of the edge connecting vertex i to vertex j. A zero corresponds to there not being a connection between i and j. If matrix[i][j] == matrix[j][i], then you have an undirected graph. Furthermore, a random graph would have random values as the edges between vertices.
In the case where every edge either exists or doesn't exist (i.e. weights are either 0 or 1), you could have the following:
This image is stolen from the internet, so I take no credit for it. Note that you can easily confirm that the first graph is undirected because the adjacency matrix is symmetric. Likewise, the second graph is directed because the matrix is NOT symmetric.
Related
I can not correctly correct the code so that the graph was undirected. By input, by condition, there should be a number of vertices, edges and then a list of adjacent vertices and their weight
using namespace std;
const int inf = 10000000;
struct edge {
int u, v, w;
};
int n, m, v, i;
vector<edge> e;
void solve() {
vector<int> d(n, inf);
d[v] = 0;
for (;;) {
bool any = false;
for (int j = 0; j < m; ++j)
if (d[e[j].u] < inf)
if (d[e[j].v] > d[e[j].u] + e[j].w) {
d[e[j].v] = d[e[j].u] + e[j].w;
any = true;
}
if (!any) break;
}
cout << d[d.size()-1] << endl;
}
int main() {
cin >> n >> m;
edge t;
for (i = 0; i<m; i++)
{
cin >> t.u >> t.v >> t.w;
t.u--; t.v--;
e.push_back(t);
}
solve();
}
From mathematical point of view an undirected graph should be equivalent to a directed one if you substitute every undirected edge with a pair of directed edges with opposite directions.
As far as I can see, you are trying to implement the Bellman-Ford algorithm. Some notes regarding your implementation. As I can see, your v global variable is not initialized properly. Is that intentional to assume that the source is the vertex with the index 0? Bellman-Ford finds the shortest paths from the source to all other vertices; you output the length of the path to the vertex with the maximum index, is that what you expect?
One major issue: what would happen if you have a negative cycle (that is possible, as you use signed int for storing the weights)? The benefit of the Bellman-Ford algorithm is that it works correctly if some of the graph's edges have negative weights. Moreover, it allows you to detect the presence of negative cycles, but in your case the algorithm would get into an infinite loop. The solution is to limit the number of iterations with n; if on the n-th iteration you find that you still haven't left the loop, there is an negative cycle in your graph.
I would like to write prims and dijkstra algoritms that create a MST. But I do not know what is the best way to represent graph in c++.
I could represent an edge by pair of two ints for example vector 0 to 1 would be pair(0,1);
typedef pair<int, int> Edge;
And then the prims function would take Vector of pairs that consist of an edge and its weight.
void prims(vector<pair<Edge, int>>);
I think that this way is not the best one, could anyone tell me what way would be the best to represent a graph?
I have been implementing Dijkstra some time ago for finding paths in binary images. I represented a graph as a vector of a struct GraphNodes that contained a vector of Connections that contained all the connections of the node to other nodes. Each connection has its distance attribute, which is the weight of the edge. Here are the two structs I used:
//forward declaration
struct GraphNode;
struct Connection {
Connection() : distance(1) { };
Connection(GraphNode* ptr, double distance) : ptr(ptr), distance(distance) { };
bool operator==(const Connection &other) const;
GraphNode* ptr;
double distance;
};
struct GraphNode {
GraphNode() : connections(8), predecessor(NULL), distance(-1) { };
cv::Point point;
double distance;
GraphNode* predecessor;
std::vector<Connection> connections;
};
bool Connection::operator==(const Connection &other) const {
return ptr == other.ptr && distance == other.distance;
}
The distance attribute of the GraphNode is the distance it currently has in the Dijkstra algorithm, so the distance of the shortest currently known distance to the start node. At the beginning this is initialized with -1.
I then implemented the Dijkstra algorithm like this:
std::vector<cv::Point> findShortestPathDijkstra(std::vector<GraphNode>& graph, int startNodeIndex, int destNodeIndex) const {
GraphDistanceSorter sorter(graph);
std::set<GraphNode*, GraphDistanceSorter> unusedNodes(sorter);
for (int i = 0; i < graph.size(); ++i) {
unusedNodes.insert(&graph[i]);
}
while (unusedNodes.size() > 0) {
GraphNode* currentNode = *unusedNodes.begin();
if (currentNode->distance == -1) {
return std::vector<cv::Point>();
}
if (currentNode == &graph[destNodeIndex]) break;
unusedNodes.erase(currentNode);
//update distances of connected nodes
for (Connection const& con : currentNode->connections) {
/*here we could check if the element is really in unusedNodes (search, O(log n)), but this would
actually take longer than calculating the new distance (O(1)), which will in this case always be greater
than the old one, so the distance is never updated for nodes not in unusedNodes ()*/
double newDistance = currentNode->distance + con.distance;
if (newDistance < con.ptr->distance || con.ptr->distance == -1) {
unusedNodes.erase(con.ptr);
con.ptr->distance = newDistance;
con.ptr->predecessor = currentNode;
unusedNodes.insert(con.ptr);
}
}
}
//now trace back the path as a list of points
std::vector<cv::Point> points;
GraphNode* current = &graph[destNodeIndex];
points.push_back(current->point);
while (current != &graph[startNodeIndex]) {
if (current->predecessor == NULL) return std::vector<cv::Point>();
current = current->predecessor;
points.push_back(current->point);
}
return points;
}
As you see there is a set unusedNodes that contains all the unused nodes so far. It only contains pointers on graphNodes. The actual graph representation is in the vector. The advantage of having a set is, that it is always sorted according to a certain criterion. I implemented my own sorter GraphDistanceSorter that sorts the GraphNodes according to the distance criterion of the Dijkstra algorithm. This way I just have to pick the first node from the set and know that it's the one with the smallest distance:
struct GraphDistanceSorter {
bool operator() (const GraphNode* lhs, const GraphNode* rhs) const;
};
bool GraphDistanceSorter::operator() (const GraphNode* lhs, const GraphNode* rhs) const {
if (lhs->distance == rhs->distance) {
return lhs < rhs;
} else {
if (lhs->distance != -1 && rhs->distance != -1) {
if (lhs->distance != rhs->distance) {
return lhs->distance < rhs->distance;
}
} else if (lhs->distance != -1 && rhs->distance == -1) {
return true;
}
return false;
}
}
The two main ways to represent graphs learned in theoretical computer-science are adjacency matrix and adjacency lists.
Adjacency Matrix is as shown in the photo below is an n*n matrix and a[i][j] represents the edge between node i and node j so if it's a weighted graph it can be an integer instead of a boolean value for unweighted graphs.
adjacency matrix (photo source: google)
On the other hand, adjacency lists is a set of linked-lists (n-set to be exact), the i-th set has exactly the nodes i is connected to.
in this case you will need some additional way to save edge distance for example you can build your own class Edge as following
class Edge
{
int destination, length;
Edge* next = 0;
}
and use it for your linked-list. How ever I am used to std::vector<std::pair<int, int>> a[N] to define a list of pairs and a[i][j].first would be the j-th neighbor of nod i and a[i][j].second the length of the edge between them.
For undirected graph your can add i to j neighbors as well.
So it's also a flexible way to represent graphs.
adjacency lists (image source: google photos)
So now let's talk complexity, I will try to keep it as simple as possible:
We habe n lists, each has the #(edges going out of node i)
so the total number is sum of this numbers which is the total number of edges E.
That means place complexity is O(E) which is at most 5 * n in a sparse-graph in comparison to O(N^2) in adjacency matrix. (We need a linear factor of E to represent it).
Now let's consider visiting all neighbors of a nod x:
in adjacency matrix we will go through the whole x-th line and if it's not 0 there's an edge there which is O(N).
In adjacency lists it's again exactly the number of neighbors of x which can though reach O(N).
But if we are visiting all neighbors of all Nodes (which is the case in Dijkstra when updating dis array), you will need to visit n elements n times in adjacency lists which is also O(N^2) time complexity while in adjacency lists it's exactly the sum of the number of neighbors - again E. which means we need also O(E) to visit all neighbors of all edges.
And sind all edges are given usually in the input O(E) would pass as calculation time, but O(N^2) would be a high complexity for constraints of N <= 10^6 for example.
At the end I will leave you with my usual implementation of diffreent variants of graphs using adjacency lists (vector as a list):
#include<iostream>
#include<vector>
int main(){
const int N = 5;
int n, e;
std::vector<std::pair<int, int>> graph[N], inverse[N];
std::vector<int> unweighted[N], undirectedUnweighted[N];
std::cin >> n >> e;
for(int i = 0; i < e; i++)
{
int x, y, z;//z is length of edge
std::cin >> x >> y >> z;
//substitute 1 from x, y if they starts from 1
graph[x].push_back(std::make_pair(y, z));
inverse[y].push_back(std::make_pair(x, z));
unweighted[x].push_back(y);
undirectedUnweighted[x].push_back(y);
undirectedUnweighted[y].push_back(x);
}
return 0;
}
Simple form for representing graph (finding neighbors and degrees for vertices)
#include<iostream>
/** Representing graphs in c++ programming language */
using namespace std;
int main() {
cout << "\033[1;33mNote: if there are no neighbourhood between vertices write '-' symbol!\033[0m\n"<<endl;
int number_of_vertices;
cout<<"\033[1;32mPlease enter number of vertices: \033[0m";
cin>>number_of_vertices;
int max_num_of_neighbours;
cout<<"\033[1;32mPlease enter maximum number of neighbours: \033[0m";
cin>>max_num_of_neighbours;
char array[number_of_vertices][max_num_of_neighbours];
char vertices[number_of_vertices];
cout<<"\033[1;33mPlease sign vertices with lowercase alphabet letters: \033[0m"<<endl;
for(int i = 0; i < number_of_vertices; i ++) {
cout<<(i+1)<<" = ";
cin>>vertices[i];
}
for(int i = 0; i < number_of_vertices; cout<<endl, i ++) {
cout<<"\033[1;32mPlease enter neighbours for \033[0m"<<vertices[i]<<" --> ";
for(int j = 0; j < max_num_of_neighbours; j ++) {
cin>>array[i][j];
}
}
for(int i = 0; i < number_of_vertices; cout<<endl, i ++) {
cout<<"\033[1;34mNeighbours for \033[0m"<<"\033[1;35m"<<vertices[i]<<"\033[0m"<<" --> ";
int deg = 0;
for(int j = 0; j < max_num_of_neighbours; j ++) {
if(array[i][j] != '-') {
deg ++;
}
if(array[i][j] == '-') {
cout<<"\033[1;31m"<<array[i][j]<<"\033[0m"<<"\t";
} else {
cout<<"\033[1;32m"<<array[i][j]<<"\033[0m"<<"\t";
}
}
cout<<"\033[1;36m"<<"deg["<<"\033[0m"<<"\033[1;35m"<<vertices[i]<<"\033[0m"<<"\033[1;36m"<<"] = "<<"\033[0m"<<deg;
}
cout<<endl<<"\033[1;33mRemember that '\033[1;31m-\033[0m\033[1;33m' shows when two vertices aren't adjacent!\033[0m"<<endl;
}
For adding interactivity I used How do I output coloured text to a Linux terminal? for changing color of text
So I'm pretty new to C++ but i think im gettting the hang of it a bit.
As part of an excersize, I have to take an input text file and apply this in a "shortest distance algorithm" where ultimatly I want to output all the shortest distances and routes but i haven't gotten that far yet. I have used the Floyd Warshall algorithm.
For now my question is, how do i replace a self written int array by a text input. the input array is just numbers but actually represents distances between nodes. The test array that im using now only has 3 nodes, but i want to be able to expand it to a much larger node amout, say 100.
example test matrix:
0 1234567 100
1234567 0 400
100 400 0
Should be read as:
node1 node2 node3
node 1 0 999999 100
node 2 999999 0 400
node 3 100 400 0
The large numbers: 999999 represents a distance that is too large too count as a edge.
As of now my code looks something like this:
#include<stdio.h>
// Number of vertices
#define V 3
// Define 999999 as a distance that is too large to represent a edge connection
#define TooLarge 999999
// The print function
void printSolution(int dist[][V]);
// Distance algorithm
void Distance (int distgraph[][V])
{
// output matrix that will have the shortest distance for every vertice
int dist[V][V], i, j, k;
// initial values for shortest distance are based on shortest paths.
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = distgraph[i][j];
// Add all vertices to the set of intermediate vertices.
for (k = 0; k < V; k++)
{
// use all vertices as seperate source
for (i = 0; i < V; i++)
{
// use all vertices as destination for the earlier determined source
for (j = 0; j < V; j++)
{
// If vertex k is on the shortest path from i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// Print the shortest distance matrix
printSolution(dist);
}
// The print function
void printSolution(int dist[][V])
{
printf ("Shortest distance matrix \n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (dist[i][j] == 999999)
printf("%7s", "TooLarge");
else
printf ("%7d", dist[i][j]);
}
printf("\n");
}
}
// driver program to test above function
int main()
{
int distgraph[V][V] = { {0, 1234567, 100},
{1234567, 0, 400},
{100, 400, 0,},
};
// Print the solution
Distance(distgraph);
return 0;
}
Hopefully someone can help me, I have the feeling im just forgetting something stupid. I have tried to inport the textfile using this type of code:
using namespace std;
double distances [3][3];
int main () {
int x, y;
ifstream in("citytest.txt");
if (!in) {
cout << "Cannot open file.\n";
return 0;
}
for (y = 0; y < 3; y++) {
for (x = 0; x < 3; x++) {
in >> distances[x][y];
}
}
cout << distances[3][3] << " " << endl;
in.close();
Which i know works, but only inports a predetermind part of the matrix whereas i want to input the entire array. (the cout function is just there to test if the correct distances were given as an input)
You cannot efficiently allocate the container unless you know big the workload in your external data file is.
Thus:
tokenize the first line of your file and take the dimension N from that
allocate your container accordingly
then consume the rest of the file and put the data into the container; maybe throw if a row's length doesn't match N, or if there are not N rows.
You may consider that
representing a graph by a full adjacency matrix is a debatable concept; it's space-inefficient and time-inefficient for sparse graphs
a 2D c-array is not the only possible representation of a matrix; you may consider a flat std container and implement a slice-style access on it
last not least you may want to have a look at boost::graph
I recently just started to learn c++ and for my next homework assignment I have to implement a bidirectional version of dijkstra's algorithm. I'm supposed to build on my last assignment which makes a graph using vectors. I'm wondering what the best way to setup this assignment using my code. Here is the actual assignment:
Machine Problem 3: Bidirectional shortest path algorithm : Ira Pohl Jan 24, 2014
Objective : Improve your Graph Class and add Dijkstra and Bidirectional algorithm
Graph algorithms and graph representation is a critical tool in CS. The basic problem will be to write Dijkstra’s algorithm as a class member function (method in OO speak). You should already know Dijkstra’s algorithm for the shortest path problem from prior experience, but it will be reviewed in class. It is the basis for many route calculations and optimizations programs.
There are 2 basic implementations used for graphs – one is edge lists, and the other is connectivity matrices. You can decide which to use, but comment on your choice.
Basic problem: Write a set of constructors for declaring and initializing a graph or use your previous implementation of graph. An edge will have a positive cost that is its distance. Have a procedure that can for a graph of at least size 1000 produce a randomly generated set of edges with positive distances. Assume the graphs are undirected. The random graph procedure should have edge density as a parameter and distance range as a parameter. So a graph whose density is 0.1 would have 10% of its edges picked at random and its edge distance would be selected at random from the distance range. This of course was already developed in problem 2.
The Dijkstra bi-directional algorithm should re-use code from the Dijkstra unidirectional algorithm.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <cmath>
double probability(){ return 1.0*rand()/RAND_MAX;}
using namespace std;
//class that has make_graph as constructor
class Graph{
public:
Graph(int s, double density);
void print_graph();
private:
int size;
vector<vector<bool> > g1; //A vector of vectors of bools
//Think of a vector as a first in, last out Data Structure
};
//make_graph altered to work in c++
Graph::Graph(int s, double density){
this->size = s;
for (int i = 0; i < s; ++i){
// We push a new vector of bool onto the initial vector s times
// The * is there to dereference the new vector that we insert
this->g1.push_back( *( new vector<bool>() ) );
for (int j = 0; j < s; ++j){
//then, on each of those vectors, we push a default "false" s times
this->g1.at(i).push_back(false);
}
}
//Don't have to change this part much
for (int i = 0; i < s; ++i){
for (int j = 0; j < s; ++j){
if (probability()< density) this->g1[i][j] = true;
}
}
}
//simple conversion, just needed 'this'
void Graph::print_graph(){
cout << "graph size " << this->size << "\n";
for(int i = 0; i < this->size; ++i){
for (int j = 0; j < this->size; ++j){
cout << this->g1[i][j] << "\t";
}
cout << "\n";
}
}
int main(){
srand(time(0));
cout << "Test simple graph generation\n";
Graph* test1 = new Graph(10, 0.7);
test1->print_graph();
cout << "\nEND of TEST 1\n\n";
Graph* test2 = new Graph(8, 0.5);
test2->print_graph();
cout << "\nEND of TEST 2\n\n";
return 0;
}
I need help with a pseudocode for an algorithm that solves the 3-edge connectivity problem:
input: a graph G in adjacency matrix format
output: true if, for every pair of vertices v,w elements of G, there exists a path from v to w of length at most 3
Any Ideas? This is what I have so far.
const int WIDTH = 10;
const HIGHT =10;
Int arrayMatrix [WIDTH] [HIGHT];
for (int i =0; i< WIDTH; i++)
{
for (int j =0; j<HIGHT; j++)
{
int countEdges =0;
countEdges = countEdges +arrayMatrix [i];
}
if countEdges<=3
cout << "True for 3-edge connectivity problem" << endl;
else
cout <<"Not found" << enld;
you can use a technique similar to the Warshall-Floyd algorithm, to compute G^3, but where for matrix multiplication you have the following operation
(X * Y)ij = OR [all k] (Xik AND Ykj).
now compute (G*G)*G (with your input adjacency matrix).
Return true if the result matrix contains only 'true' elements.