Storing Data into a Linked List C++ - c++

The input is in the following format.
5
1 2 9.0
1 3 12.0
2 4 18.0
2 3 6.0
2 5 20.0
3 5 15.0
0
1 5
The first number is the number of vertexes in the graph. Then next lines up to 0 are the edges of the graph. With the first and second numbers being the vertexes and the third being how far the edge is between them. I can not figure out how to store the data into the List adjacency for each of the vertexes when reading it in. EX. Vertex 1 would have two List cells containing 2 9.0 and 3 12.0. I would also need to put the 1 9.0 and 1 12.0 into vertexes 2 and 3. But I can not figure out how to store the data into the ListCells
Code so Far:
#include <cstdio>
using namespace std;
typedef ListCell* List;
struct ListCell
{
ListCell* next;
int vertex;
double weight;
ListCell(int v, double w, ListCell* nxt)
{
vertex = v;
weight = w;
next = nxt;
}
};
struct Vertex
{
bool signaled;
long distance;
Vertex next;
List adjacency;
};
struct Graph
{
int numVertices;
Vertex* vertexInfo;
Graph(int n)
{
numVertices = n;
vertexInfo = new Vertex[n+1];
for(int i = 1; i <= n; i++)
{
vertexInfo[i].signaled = false;
}
}
};
//==============================================================
// readIn
//==============================================================
//
//==============================================================
void readIn()
{
int n, p1, p2;
double edge;
scanf("%i ", &n);
Graph(n);
while(scanf("%i " &p1) != 0)
{
}
}

I use to define data structures in a way suitable for the business logic.
I would suggest you have a look on The Art of Computer programming to have an idea of some best practices.
Put an eye on "Linear Lists" chapter
hint:
traverse the list and append the new node (please take care of corner cases):
Vertex* v = vertexInfo[i];
while (v->next!=null) {
v = v->next;
}
v->next = new Vertex(....);

Related

Maximum cost path in an Undirected Graph such that no edge is visited twice

I have a graph where each node has a numeric value. Starting from a node of my choice, I have to find the path where the sum of the node values is the heaviest. However I can only cross the same bridge once BUT it is possible to pass several times on the same node.
For example if I have a undirected graph like this:
EDGES
0 1
0 2
0 3
1 2
1 4
and each node have a weight like this:
Node weight
0 -> 4
1 -> 3
2 -> 7
3 -> 2
4 -> 9
If I start from the source "1", the path's output should be like this
1->2->0->1->4 with total weight of 23.
I'm trying to solve this problem with DFS in this way:
int dfs(vector<vector<int> >& g, int* cost, int u, int pre)
{
vis[u] = true;
dp[u] = cost[u];
bool check = 1;
int cur = cost[u];
for (auto& x : g[u]) {
if (vis[x] && x != pre) {
check = 0;
} else if (!vis[x]) {
check &= dfs(g, cost, x, u);
cur = max(cur, cost[u] + dp[x]);
}
}
dp[u] = cur;
if (!check) {
canTake += cost[u];
} else {
best = max(best, dp[u]);
}
return check;
}
int FindMaxCost(vector<vector<int> >& g,int* cost, int source)
{
dfs(g, cost, source, -1);
cout << canTake + best;
}
With this I can find the right total weight but I don't know how
to save the right path.
I'm trying to take the path picking u-node in this code:
if (!check) {
canTake += cost[u];
// taking the u-node
} else {
best = max(best, dp[u]);
// taking here the last node in global variable
}
but the path is not correct.

How to implement Dijkstra Algorithm for finding shortest path from 1 node to all other in an undirected graph in C and print the distances as well

There is an undirected graph. You need to store all edge weights in a two-dimensional array cost[][], and calculate the shortest distance from the source node 0 to all other nodes. Suppose there are at most 100 nodes. If there is no edge between two nodes, we set their weight to a very large number, MAX_DIS=999999, to denote these two nodes are not connected directly.
In this exercise, you are required to fulfill the following two tasks.
Initialize Cost Array
Initially, we have the array cost[100][100] to store the edge cost. We input the total nodes number n and edges number m, and the input all edges with <x,y,w> format, where w is the weight of edge (x,y). If there is no edge between two nodes, we set the cost MAX_DIS.
Calculate Shortest Distance.
With the cost array, we need to compute the shortest distance between node 0 and all other nodes. Also, we need to initialize the distance array distance[100] at first. Then in each loop, we first find the min distance distance[w] and update other distance distance[v] if node v is adjacent to w.
//Below is my code for this challenge, but it is not working properly for all the test cases. It works fine for some but I can't figure out where is the problem. I hope this is a good challenge to be solved and that is why I am posting it here. Can you guys help me debug this code...
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX_NODES 100
#define MAX_DIS 999999
int cost[MAX_NODES][MAX_NODES];
int distance[MAX_NODES];
void initial(int m, int n);
void Dijkstra(int n);
void initial(int m, int n)
{
/*
let user input all edges and their weights and initialize cost[][].
note that if no edge between (x,y), set cost[x][y]=MAX_DIS
and cost[a][b]=cost[b][a] for the undirected graph.
Fill in your code here...
*/
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
cost[i][j] = MAX_DIS;
}
}
cost[0][0] = 0;
int weight,x,y;
for(i=0; i < m; i++){
scanf("%d %d %d", &x,&y,&weight);
cost[x][y] = weight;
cost[y][x] = weight;
}
}
void Dijsktra(int n)
{
/*
Fill in your code here...
calculate the distance from node 0 to all other nodes.
*/
int i;
int S[n];
S[0] = 1;
int all_visited = 0;
for(i=1;i<n;i++){
S[i] = -1;
}
for(i=0;i<n;i++){
distance[i] = cost[0][i];
}
while(all_visited != 1){
int temp = MAX_DIS;
int pos = -1;
for(i=1;i<n;i++){
if(S[i] == -1 && cost[0][i] <= temp){
temp = cost[0][i];
pos = i;
}
}
S[pos] = 1;
for(i=0;i<n;i++){
if(S[i] == -1)
break;
}
if(i==n)
all_visited = 1;
for(i=1; i<n; i++){
distance[i] = (int)fmin(distance[i], distance[pos] + cost[pos][i]);
}
}
}
int main()
{
int m,n;
printf("Input the number of nodes:\n");
scanf("%d",&n);
printf("Input the number of edges:\n");
scanf("%d",&m);
printf("Input these edges:\n");
initial(m,n);
Dijsktra(n);
for(int i=0;i<n;i++)
printf("%d ",distance[i]);
return 0;
}
This is test case for which my code is failing -
Input the number of nodes:
8
Input the number of edges:
10
Input these edges:
0 1 2,
1 2 9,
2 3 4,
3 5 7,
2 4 8,
5 6 10,
6 7 8,
7 5 1,
7 3 4,
0 4 10
Expected output - 0 2 11 15 10 20 27 19
My output - 0 2 11 15 10 999999 999999 999999
use a break statement in this loop.
for(i=1;i<n;i++){
if(S[i] == -1 && cost[0][i] <= temp){
temp = cost[0][i];
pos = i;
break; //here
}
}

BFS traversal giving wrong output

I am trying to solve the problem using the adjacency list now. But the problem I am facing here is when I am trying to insert the element in an adjacency list, it stores the value in the sequence I have entered.
For example for the test case:
5 8 0 1 0 4 1 2 2 0 2 4 3 0 3 2 4 3
My output is:
0 1 4 2 3
Expected output is:
0 1 2 3 4.
It is because my adjacency list stores the value in the fashion it was not entered in a sorted manner. How would I store it in a sorted manner? If I sort it, it just increases the complexity of the code. Please help.
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
void addEdge(vector<ll> edges[], ll u, ll v)
{
edges[u].push_back(v);
edges[v].push_back(u);
}
void BFS(vector<ll> edges[], ll v, bool * visited, queue<ll> q)
{
while(!q.empty())
{
ll s = q.front();
cout << s << " ";
q.pop();
for(ll i = 0; i < edges[s].size(); i++)
{
if(!visited[edges[s][i]])
{
visited[edges[s][i]] = true;
q.push(edges[s][i]);
}
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
ll v, e;
cin >> v >> e;
vector<ll> edges[v];
for(ll i = 0 ; i < e; i++)
{
int x, y;
cin >> x >> y;
addEdge(edges, x, y);
}
bool * visited = new bool[v];
memset(visited, false, sizeof(visited));
queue<ll> q;
q.push(0);
visited[0] = true;
BFS(edges, v, visited, q);
return 0;
}
Yes, you were right, the behaviour is due to the order in the input.
You could try using a priority queue instead of a simple vector for your adjacency list, to keep your vertices in a specific order, but this does add complexity to your algorithm.

Parallelizing Boruvka with openMP

I have implemented Boruvka's algorithm sequentially in C++ and I know one of the advantages of the algorithm is that it can easily be paralleled. I am trying to do this using openMP, but I can't figure out how to get it to work. I read in an adjacency list from graph.txt and print my output of the minimum spanning tree into mst.txt. Here is my sequential code for boruvka:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
// initialize data structure for edges (given in adjacency list)
struct Edge {
int v1, v2, weight; // 2 connecting verticies and a weight
};
// initialize structure for the graph
struct Graph {
int vertex, edge;
Edge* e; // undirected graph so edge from v1 to v2 is same as v2 to v1
};
// Creates a graph for #verticies and #edges using arrays
struct Graph* formGraph(int vertex, int edge)
{
Graph* graph = new Graph;
graph->vertex = vertex;
graph->edge = edge;
graph->e = new Edge[edge]; // again, v1-v2 = v2-v1
return graph;
}
// initialize structure for subsets within the graph
struct Subset {
int parent, rank; // rank will act as counter
};
// will help to find lightest edge of sets recursively
int find(struct Subset subset[], int i)
{
if (subset[i].parent != i) {
subset[i].parent = find(subset, subset[i].parent);
}
// once it is =1
return subset[i].parent;
}
// A function that does union of two sets
void Union(struct Subset subs[], int set1, int set2)
{
int root1 = find(subs, set1);
int root2 = find(subs, set2);
//union by ranking
if (subs[root1].rank < subs[root2].rank) { // if rank2 is higher thats parent
subs[root1].parent = root2;
}
else if (subs[root1].rank > subs[root2].rank) { // if rank1 is higher thats parent
subs[root2].parent = root1;
}
else // ranks are the equal so increment rank by 1
{
subs[root2].parent = root1;
subs[root1].rank++;
}
}
// the boruvka algorithm implementation
void boruvka(struct Graph* graph) {
// set data of initial graph
int vertex = graph->vertex;
int edge = graph->edge;
Edge* e = graph->e;
//initially there will always be as many subsets as there are vertices
struct Subset *subs = new Subset[vertex];
int *lightest = new int[vertex]; // array storing least weight edge
// subset for each vertex
for (int v = 0; v < vertex; v++)
{
subs[v].parent = v; // initial parent (none)
subs[v].rank = 0; // initial rank (no parent so always 0)
lightest[v] = -1; // start from -1
}
int components = vertex; // iniitial trees = number of verticies
int minWeight = 0;
// must keep going until there is only one tree
while (components > 1)
{
// lightest weight for all edges
for (int i=0; i<edge; i++)
{
// gets subsets for edges that could connect
int set1 = find(subs, e[i].v1);
int set2 = find(subs, e[i].v2);
// waste of time if they're already in same set so don't check
if (set1 == set2)
continue;
// if different then check which one is lightest
else
{
if (lightest[set1] == -1 || e[lightest[set1]].weight > e[i].weight) {
lightest[set1] = i;
}
if (lightest[set2] == -1 || e[lightest[set2]].weight > e[i].weight) {
lightest[set2] = i;
}
}
}
// making sure the wieghts are added
for (int i=0; i<vertex; i++)
{
// make sure all lightest edges are included
if (lightest[i] != -1)
{
int s1 = find(subs, e[lightest[i]].v1);
int s2 = find(subs, e[lightest[i]].v2);
if (s1 == s2)
continue;
minWeight += e[lightest[i]].weight;
// Need to sort output lexicographically!?!?!?!?!!
printf("Edge %d-%d included in MST with weight %d\n", // prints verices and weight of edge
e[lightest[i]].v1, e[lightest[i]].v2,
e[lightest[i]].weight);
// union subsets together, decrease component number
Union(subs, s1, s2);
components--;
}
lightest[i] = -1; // in case after first iteration lightest edges fall in same subset
}
}
printf("Weight of MST is %d\n", minWeight);
return;
}
// main function for calling boruvka
int main() {
ifstream infile;
char inputFileName[] = "graph.txt"; // input filename here
infile.open(inputFileName, ios::in);
string line;
getline(infile, line);
int V = atoi(line.c_str()); // set num of vertices to first line of txt
getline(infile, line);
int E = atoi(line.c_str()); // set num of edges to second line of txt
// create graph for boruvka
struct Graph* graph = formGraph(V, E);
if (infile.is_open()) {
string data[3]; // initialize data array
int count = 0; // initialize counter
while (infile.good()) { // same as while not end of file
getline(infile, line);
stringstream ssin(line);
int i = 0;
while (ssin.good() && i < 3) {
ssin >> data[i];
i++;
}
graph->e[count].v1 = atoi(data[0].c_str());
graph->e[count].v2 = atoi(data[1].c_str());
graph->e[count].weight = atoi(data[2].c_str());
count++;
}
}
freopen("mst.txt","w",stdout); // writes output into mst.txt
// call boruvka function
boruvka(graph);
infile.close(); // close the input file
return 0;
}
An example of my graph.txt is this:
9
14
0 1 4
7 8 7
1 2 8
1 7 11
2 3 7
2 5 4
2 8 2
3 4 9
3 5 14
4 5 10
5 6 2
6 7 1
6 8 6
0 7 8
The output for this example which is correct that is placed in my mst.txt is this:
Edge 0-1 included in MST with weight 4
Edge 2-8 included in MST with weight 2
Edge 2-3 included in MST with weight 7
Edge 3-4 included in MST with weight 9
Edge 5-6 included in MST with weight 2
Edge 6-7 included in MST with weight 1
Edge 1-2 included in MST with weight 8
Edge 2-5 included in MST with weight 4
Weight of MST is 37
According to the algorithm, in each iteration, each tree in the forest will have one and only one edge added to the forest independently (edges from different trees could be the same), until the added edges connect the whole forest into a single tree.
Here you can see finding the only edge for each tree can be done in parallel. As long as you have more than one tree, you could use multiple threads to speed up the searching.
if you're interested, I've written an implementation of the parallel Boruvka's algorithm using OpenMP.
We store the graph as an edge list (edges) where each edge (u, v) appears twice: as an edge from u and from v. At each step of the algorithm, edges is sorted in O(E log E) = O(E log V) time.
Then edges are split between P processors. Each one of them calculates the array of shortest edges from its local nodes. Because allocating raw memory for all nodes is done in constant time, we can simply store this as an array and avoid using hashmaps. Then we merge the results between processors into a global shortest edge array using compare and swap. Note that because we sorted the edge list previously, all edges from u make up a continuous segment in edges. Because of this, the total number of extra iterations in the cas loop does not exceed O(P) which gives us O(E / P + P) = O(E / P) time for this step.
After that, we can merge components along the added edges in O(V * alpha(V) / P) time using a parallel DSU algorithm.
The next step is updating the list of vertices and edges, this can be done using parallel cumulative sum in O(V / P) and O(E / P) respectively.
Since the total number of iterations is O(log V), the overall time complexity is O(E log^2 V / P).

Reading in to Linked-List not Working correctly C++

I have been stuck on this problem for hours will someone please help.
The input is in the following format
5
1 2 9.0
1 3 12.0
2 4 18.0
2 3 6.0
2 5 20.0
3 5 15.0
0
1 5
The first number is the number of vertexes in the graph. Then next lines up to 0 are the edges of the graph. With the first and second numbers being the vertexes and the third being how far the edge is between them. Trying to read in the data and store the edges into there locations in the List adjacency for that vertex. This example would make a graph with five vertexes with edges from 1 to 2&3. 2 to 4&3&1 etc also stores opposites EX. 2 1 9.0.
It is not storing the data correctly. When reading in each new data for each vertex overwrites the previous data. It is storing the data in multiple listCells because when printed out i get
1 3 12.000
1 3 12.000
2 5 20.000
2 5 20.000
2 5 20.000
2 5 20.000
3 5 15.000
3 5 15.000
3 5 15.000
So it is the write number of cells just wrong information.
#include <cstdio>
using namespace std;
int tracing= 1;
struct ListCell
{
ListCell* next;
int vertex;
double weight;
ListCell(int v, double w, ListCell* nxt)
{
vertex = v;
weight = w;
next = nxt;
}
};
typedef ListCell* List;
struct Vertex
{
bool signaled;
long distance;
List adjacency;
};
struct Graph
{
int numVertices;
Vertex* vertexInfo;
Graph(int n)
{
numVertices = n;
vertexInfo = new Vertex[n+1];
for(int i = 1; i <= n; i++)
{
vertexInfo[i].signaled = false;
}
}
};
//==============================================================
// tail
//==============================================================
//
//==============================================================
List tail(List L)
{
return L->next;
}
//==============================================================
// isEmpty
//==============================================================
//
//==============================================================
bool isEmpty(List L)
{
return L == NULL;
}
//==============================================================
// readIn
//==============================================================
//
//==============================================================
Graph readIn()
{
int g;
int p1;
int p2;
float edge;
scanf("%i ", &g);
Graph myGraph(g);
scanf("%i", &p1);
while(p1 != 0)
{
scanf("%i", &p2);
scanf("%f", &edge);
if(tracing >0)
{
printf("Edge from %i to %i is %5.3f\n", p1, p2, edge);
}
myGraph.vertexInfo[p1].adjacency = new ListCell
(p2,edge,myGraph.vertexInfo[p1].adjacency);
myGraph.vertexInfo[p2].adjacency = new ListCell
(p1, edge, myGraph.vertexInfo[p2].adjacency);
scanf("%i", &p1);
}
return myGraph;
}
//==============================================================
// printOut
//==============================================================
//
//==============================================================
void printOut(Graph myGraph)
{
int n;
int length = myGraph.numVertices;
float d;
List p;
printf("There are %i vertices.\n", length);
printf("The edges are as follows. \n\n");
for(int i=1; i<=length; i++)
{
p= myGraph.vertexInfo[i].adjacency;
for(p=p; !isEmpty(p); p=tail(p))
{
n = myGraph.vertexInfo[i].adjacency -> vertex;
d = myGraph.vertexInfo[i].adjacency -> weight;
if(i<n)
{
printf("%i %i %7.3f \n",i,n,d);
}
}
}
}
//==============================================================
// main
//==============================================================
int main(int argc, char** argv)
{
Graph myGraph = readIn();
printOut(myGraph);
return 0;
}
There is a lot wrong with your code. The first thing and probably the most glaring is this:
myGraph.vertexInfo[p1].adjacency = new ListCell
(p2,edge,myGraph.vertexInfo[p1].adjacency);
you call this in the input loop. Look at your first vertex you input (1). You input this twice, one time for "1 2 9.0", and again for "1 3 12.0". The variable p1 doesn't change (it remains at 1), but you're overwriting the first input with the second input.
So you not only have an error in the input, you have a memory leak since you're creating a ListCell dynamically, and overwriting the previous dynamically allocated ListCell.
Maybe an array is not what you should use as a vertexInfo. Maybe it should be a map of vertex to vertices/distances:
std::map<int, std::vector<std::pair<int,double>>>
where the key is the vertex, and the inner vector is a vector of all the adjacent vertices and distances (each one represented as a pair).