How to use a queue to count the number of graph components? - c++

I have the queue functions and I have to use them to count the number of graph components. These are my functions:
struct TQueue {
int value;
TQueue * next;
};
void QueueInit(TQueue * & a_head, TQueue * & a_tail) {
a_head = NULL;
a_tail = NULL;
};
bool IsQueueEmpty(TQueue * a_head) {
return !a_head;
};
void Enqueue(TQueue * & a_head, TQueue * & a_tail, int a_val) {
TQueue * l_hlp = new TQueue;
l_hlp->value = a_val;
l_hlp->next = NULL;
if (a_tail) a_tail->next = l_hlp;
if (!a_head) a_head = l_hlp;
a_tail = l_hlp;
}
int Dequeue(TQueue * & a_head, TQueue * & a_tail) {
int l_val = a_head->value;
TQueue * l_hlp = a_head;
a_head = a_head->next;
if (!a_head) a_tail = NULL;
delete l_hlp;
return l_val;
};
void EmptyQueue(TQueue * & a_head, TQueue * & a_tail) {
TQueue * l_hlp;
while (a_head) {
l_hlp = a_head;
a_head = a_head->next;
delete l_hlp;
}
a_tail = NULL;
};
And this is my main() function and some variables:
// constant - number of vertexes
const int n = 9;
// queue declaration
TQueue *phead, *ptail;
QueueInit(phead, ptail);
// array of distanc
int dist[n];
// distanc array initialization
for (int i = 0; i < n; i++) dist[i] = -1;
// current distance
int d = 0;
// processingvertex
int v;
// number of components
int c = 0;
I prefer to use stack and DFS but it's a school projec so I must to use queue and BFS algorithm.

The approach is same as you would do in a dfs based approach. Here is a general bfs implementation using queue which you can modify easily for your purpose(i.e.using a custom queue)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void bfs(int src, vector<bool>& vis, vector<vector<int>>& adj) {
queue<int> q;
q.push(src);
vis[src] = true;
while(!q.empty()) {
int u = q.front(); q.pop();
vis[u] = true;
for(int v : adj[u]) {
if(!vis[v]) q.push(v);
}
}
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> adj(n);
for(int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
int count = 0;
vector<bool> vis(n);
for(int i = 0; i < n; i++) {
if(!vis[i]) {
bfs(i, vis, adj);
count++;
}
}
cout << count << '\n';
}
Variables reference
n : number of nodes in graph
m : number of edges in graph
adj : adjacency list representation of graph
vis : array to store if node is visited or not
count : number of connected components in graph
Example Test Case
Input:
6 3
1 5
0 2
2 4
Output:
3
You can refer to this post on mathematics stack exchange for understanding the algorithm: Finding connected components in a graph using BFS

This is my attempt to code compute components and assign vertices to components:
for (int i = 0; i <= n - 1; i++) visited[i] = false;
c = 0;
while (1) {
c++;
all = true;
for (int i = 0; i < n; i++)
if (!visited[i]) {
all = false;
visited[i] = c;
fronta::Enqueue(phead, ptail, i);
break;
}
if (all) {
c--;
break;
}
fronta::Enqueue(phead, ptail, 0);
visited[0] = true;
while (!fronta::IsQueueEmpty(phead)) {
v = fronta::Dequeue(phead, ptail);
//cout << "processing vertex: " << v << endl;
for (int j = 0; j < n; j++) {
if (gr3[v][j] && !visited[j]) {
fronta::Enqueue(phead, ptail, j);
visited[j] = true;
}
}
}
}
But it doesn't work very well...

Related

Finding the cycle in a directed graph

I was solving a problem to determine whether a graph contains a cycle. I solved it using the coloring method (in the visited array I will mark, 0 if it has never visited, 1 if it is visited, and 2 if the tour of vertex is done)
for this I wrote the code:
#include <bits/stdc++.h>
using namespace std;
vector<int> adj[20005];
int vis[20005];
int chk = 0;
void dfs(int u){
if(vis[u]==1) {
chk = 1;
return;
}
if(vis[u]==2) return;
vis[u] = 1;
for(auto v:adj[u]) dfs(v);
vis[u] = 2;
}
int main(){
int N, M; cin>>N>>M;
for(int i = 0; i<M; i++){
int p, q; cin>>p>>q;
adj[p].push_back(q);
}
for(int i = 1; i<=N; i++){
if(vis[i]==1) break;
if(!vis[i]) dfs(i);
}
cout<<(chk?"Yes\n":"No\n");
}
Now, I'm thinking, if there's a way to write the cycle which has been detected. I know most people will say DFS and backtracking and it's very intuitive. But want to know how do I implement it.
par[v] - parent node of v, pr - previously visited node:
void dfs(int u, int pr = -1){
if(vis[u]==1) {
vector<int> cycle();
int cur = pr;
while(cur != u) {
cycle.push_back(cur);
cur = par[cur]
}
cycle.push_back(u);
chk = 1;
return;
}
if(vis[u]==2) return;
vis[u] = 1;
par[u] = pr;
for(auto v:adj[u]) dfs(v, u);
vis[u] = 2;
}

C++ find the second shortest path using Dijkstras algorithm?

I have a Dijkstras algorithm program below. My program reads a text file and finds the shortest path from the start node to the goal node. My question is once this shorest path is discovered, given my code, how can I store this path? Reason being I am required to also find the second shorest path. Thankyou
#include <iostream>
#include <fstream>
#include <vector>
#include <limits.h>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <utility>
using namespace std;
#define INFINITY1 9999
int counter = 0;
int vcount = 0;
int ecount = 0;
int startVertex;
int endVertex;
int nVerticies;
int nEdges;
struct Vertex
{
int label;
int xcord;
int ycord;
};
struct Edge
{
int parent1;
int parent2;
int weight;
};
Vertex *vertArray = NULL;
Edge *edgeArray = NULL;
float distance(int x1, int y1, int x2, int y2)
{
// Calculating distance
return sqrt(pow(x2 - x1, 2) +
pow(y2 - y1, 2) * 1.0);
}
// Dijkstras
void dijkstra(vector<vector<int>> G, int n, int startnode)
{
// Get x and y cords of start node
int startx = vertArray[startnode].xcord;
int starty = vertArray[startnode].ycord;
// Get x and y cords of end node
int endx = vertArray[n].xcord;
int endy = vertArray[n].ycord;
int **cost = new int *[nVerticies];
for (int i = 0; i < nVerticies; ++i)
{
cost[i] = new int[nVerticies];
}
int distance[nVerticies], pred[nVerticies];
int visited[nVerticies], counter, mindistance, nextnode, i, j;
for (i = 0; i < nVerticies; i++)
for (j = 0; j < nVerticies; j++)
// If there is no weight, then set it to infinity
if (G[i][j] == 0)
cost[i][j] = INFINITY1;
else
{
cost[i][j] = G[i][j];
}
for (i = 0; i < nVerticies; i++)
{
distance[i] = cost[startnode][i];
pred[i] = startnode;
visited[i] = 0;
}
distance[startnode] = 0;
visited[startnode] = 1;
counter = 1;
while (counter < nVerticies - 1)
{
mindistance = INFINITY1;
for (i = 0; i < nVerticies; i++)
if (distance[i] < mindistance && !visited[i])
{
mindistance = distance[i];
nextnode = i;
}
visited[nextnode] = 1;
for (i = 0; i < nVerticies; i++)
if (!visited[i])
if (mindistance + cost[nextnode][i] < distance[i])
{
distance[i] = mindistance + cost[nextnode][i];
pred[i] = nextnode;
}
counter++;
}
for(i=n; i<n+1; i++)
if(i!=startnode)
{
cout<<"\nDistance of node "<<i+1<<"="<<distance[i];
cout<<"\nPath="<<i+1;
j=n;
do
{
j=pred[j+1];
cout<<"<-"<<j+1;
}
while(j!=startnode);
}
}
int main()
{
// Declaration for reading file
int a, b, c;
ifstream readFile;
string fileName;
// Ask for file name
cout << "Enter filename: ";
cin >> fileName;
readFile.open(fileName);
// Read last line and set start and goal vertex equal to file input
while (readFile >> startVertex >> endVertex)
{
}
readFile.close();
readFile.open(fileName);
// Read line 1 and set nVerticies and nEdges equal to file input
while (readFile >> nVerticies >> nEdges)
{
counter++;
break;
}
// Create array with size nVerticies
vertArray = new Vertex[nVerticies];
for (int i = 0; i < nVerticies; i++)
{
// Initialise all elements to zero
vertArray[i].label = 0;
vertArray[i].xcord = 0;
vertArray[i].ycord = 0;
}
// Create array with size nEdges
edgeArray = new Edge[nEdges];
for (int i = 0; i < nEdges; i++)
{
// Initialise all elements to zero
edgeArray[i].parent1 = 0;
edgeArray[i].parent2 = 0;
edgeArray[i].weight = 0;
}
vector<vector<int>> G(nVerticies, vector<int>(nVerticies, 0));
while (readFile >> a >> b >> c)
{
// Get vertex from file and add it to array
if (nVerticies >= counter)
{
vertArray[vcount].label = a;
vertArray[vcount].xcord = b;
vertArray[vcount].ycord = c;
vcount++;
counter++;
}
// Get edge from file and add it to array
else
{
G[a - 1][b - 1] = c;
G[b - 1][a - 1] = c;
edgeArray[ecount].parent1 = a;
edgeArray[ecount].parent2 = b;
edgeArray[ecount].weight = c;
ecount++;
counter++;
}
}
readFile.close();
dijkstra(G, endVertex - 1, startVertex - 1);
int n = 11;
int u = 0;
cout << endl;
cout << endl;
cout << endl;
return 0;
}
output from read file
Distance of node 1=46
Path=1<-2
Distance of node 3=65
Path=3<-1<-2
Distance of node 4=47
Path=4<-2
Distance of node 5=36
Path=5<-2
Distance of node 6=53
Path=6<-2
Distance of node 7=135
Path=7<-8<-6<-2
Distance of node 8=99
Path=8<-6<-2
Distance of node 9=95
Path=9<-4<-2
Distance of node 10=82
Path=10<-2
Distance of node 11=116
Path=11<-10<-2
Distance of node 12=76
Path=12<-2
Distance of node 13=85
Path=13<-2
Ive been guided to follow a similar pattern to the following
if you have a path of 1-->2 -->3 -->4
Set 2 to max and try again
Reset 2
Set 3 to max
Reset 3

Bellman Ford parsing Source & Destination as a Character rather than an Integer

I am working on a data structures assignment which requires me to read from a file which contains a source, destination & weight (e.g t,x,5) and I've used online resources such a geeksforgeeks from where I have altered my code to make it work. Although what I am currently doing is kind of a hack/workaround which reads the character and converts it to an integer which basically defeats the purpose.
I want to parse the characters as is and not convert it to an integer.
Reference: https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
So basically what I doing is that i am treating {s,t,x,y,z} as {0,1,2,3,4} which basically works
if(a[0]=='s')
{
graph->edge[index].src = 0;
}
and so on...
File that's being read
t,x,5
t,y,8
t,z,-4
x,t,-2
y,x,-3
y,z,9
z,x,7
z,s,2
s,t,6
s,y,7
And here is the working code for it
#include<bits/stdc++.h>
#include<fstream>
#include<string>
using namespace std;
struct Edge {
int s, d, w;
};
struct Graph {
int V, E;
struct Edge* edge;
};
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[E];
return graph;
}
void initialize_single_source(int distance[],int V, int s)
{
for (int i = 0; i < V; i++)
{
distance[i] = INT_MAX;
}
distance[s] = 0;
}
void relax(int distance[], int u, int v, int w)
{
if (distance[v] > distance[u] + w && distance[u] != INT_MAX)
{
distance[v] = distance[u] + w;
}
}
void display(int distance[], int n)
{
char vertex[] = {'s','t','x','y','z'};
cout << "Vertex Distance from Source\n";
for (int i = 0; i < n; ++i)
cout << vertex[i] << "\t\t" << distance[i] << "\n";
}
bool bellman_ford(struct Graph* graph, int s)
{
int V = graph->V;
int E = graph->E;
int distance[V];
initialize_single_source(distance,V,s);
for (int i = 1; i <= V - 1; i++)
{
for (int j = 0; j < E; j++)
{
int u = graph->edge[j].s;
int v = graph->edge[j].d;
int w = graph->edge[j].w;
relax(distance,u,v,w);
}
}
for (int i = 0; i < E; i++) {
int u = graph->edge[i].s;
int v = graph->edge[i].d;
int w = graph->edge[i].w;
if (distance[v] > distance[u] + w && distance[u] != INT_MAX)
return false;
}
display(distance, V);
return true;
}
int main()
{
int V = 5;
int E = 10;
struct Graph* graph = createGraph(V, E);
int index = 0;
string a;
ifstream infile("adjlist.txt");
while(getline(infile,a))
{
if(a[0]=='s')
{
graph->edge[index].s = 0;
}
else if(a[0]=='t')
{
graph->edge[index].s = 1;
}
else if(a[0]=='x')
{
graph->edge[index].s = 2;
}
else if(a[0]=='y')
{
graph->edge[index].s = 3;
}
else if(a[0]=='z')
{
graph->edge[index].s = 4;
}
if(a[2]=='s')
{
graph->edge[index].d = 0;
}
else if(a[2]=='t')
{
graph->edge[index].d = 1;
}
else if(a[2]=='x')
{
graph->edge[index].d = 2;
}
else if(a[2]=='y')
{
graph->edge[index].d = 3;
}
else if(a[2]=='z')
{
graph->edge[index].d = 4;
}
if(a[4]!='-')
{
graph->edge[index].w = a[4]-'0';
}
else
{
graph->edge[index].w = -(a[5]-'0');
}
index++;
}
bellman_ford(graph, 0);
return 0;
}
Output:
Vertex Distance from Source
s 0
t 2
x 4
y 7
z -2
One possible solution would be to rewrite Edge as follows
struct Edge {
char s, d;
int w;
};
and use std::map<char, vector<char> > for representing the adjacency lists. Note that this will require you to somehow keep track of the weights and change the remaining parts of the code accordingly.
On a side note, as mentioned by #user4581301, including bits/stdc++ is bad practice. See this for more details.
Converting vertex labels from strings or some other sparse type to densely packed integers is actually pretty common when implementing graph algorithms and can be quite useful.
We do this so that we can use arrays or vectors to store other things corresponding to the vertexes, instead of more complex structures like maps.
The label mapping should be constructed dynamically, though, depending on what labels you actually have instead of hard-coding it. You can use a std::map<char,int> to do it like this:
int getVertexNumber(char c) {
auto it = label_map.find(c);
int num;
if (it != label_map.end()) {
// already had a mapping for this label
num = it->second;
} else {
// new label, starting at 0
num = (int)label_map.size();
label_map[c] = num;
}
return num;
}

Subgraph with max nodes

I have the graph with N nodes. I have to create the longest subgraph (with max nodes). One node can be connected with only 2 nodes. So which nodes should I take to create this (max) subgraph?
What I'm doing is:
1: From initial node. I start 2 DFS functions. (from anothers nodes only 1).
2: For some node in DFS I use F() function to check all neighbours and find maximum way that I have to go. Then I'm saving the index of the node in which I have to go in index variable and starting DFS from index.
The problem is that this algorithm is too slow. How can I optimize it? Maybe there is special algorithm to find maximum subgraph?
Here is my code:
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int used[20];
int m[20][20];
int c;
int F(int v) {
used[v] = 1;
int maxn = 0, index = -1, t;
for(int i = 0; i < c; ++i) {
if(!used[i] && m[v][i] == 1) {
t = F(i);
if(t > maxn) {
maxn = t;
index = i;
}
}
}
if(index != -1) {
used[v] = 0;
return maxn + 1;
}
else {
used[v] = 0;
return 1;
}
}
int DFS(int v) {
used[v] = 1;
int maxn = 0, index = -1, t;
for(int i = 0; i < c; ++i) {
if(!used[i] && m[v][i] == 1) {
t = F(i);
if(t > maxn) {
maxn = t;
index = i;
}
}
}
if(index != -1) {
return DFS(index) + 1;
}
else {
return 0;
}
}
int main() {
cin >> c;
for(int i = 0; i < c; ++i) {
for(int j = 0; j < c; ++ j)
cin >> m[i][j];
}
int maxn = DFS(0) + DFS(0) + 1;
cout << maxn << endl;
}

C++: Fast algorithm for finding minimum sum of cycle edges

I have an undirected weighted graph and want to find the minimum sum of all cycles edges.
That means if I have no cycle, the answer is 0.
If I have one cycle the answer is the minimum edge weight of that cycle.
And if I have more than one cycle it's the sum of those minimum weights.
My algorithm I implemented, uses some kind of Prims algorithm.
I just add the heaviest edges and when a cycle would be formed the weight is summed to the answer value instead.
I thought it is correct as all my test cases show the right answer.
But somewhere has to be an error, I just couldn't find it yet.
struct connection {
int a, b, cost;
bool operator<(const connection rhs) const {
return cost < rhs.cost || (cost == rhs.cost && (a < rhs.a || (a == rhs.a && b < rhs.b)));
}
};
int n, m, researchers; // Amount of vertices, edges
std::list<connection> *adj; // Array of adjancency lists
std::list<int> *used;
std::set<connection> priorityQ;
void addEdge(int v, int w, int cost) {
connection temp;
temp.a = v;
temp.b = w;
temp.cost = cost;
adj[v].push_back(temp);
temp.a = w;
temp.b = v;
adj[w].push_back(temp);
}
bool isUsed(int u, int v) {
for (std::list<int>::iterator it = used[u].begin(); it != used[u].end(); ++it) {
int te = *it;
if (te == v) return true;
}
return false;
}
void expand(int u) {
for (std::list<connection>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
connection v = *it;
if (isUsed(u, v.b)) continue;
used[v.b].push_back(u);
used[u].push_back(v.b);
priorityQ.insert(v);
}
}
void PrimR(int u, bool added[]) {
added[u] = true;
expand(u);
}
// Prim algorithm
void Prim(int u, bool added[]) {
added[u] = true;
expand(u);
while (priorityQ.size() > 0) {
connection now = *priorityQ.rbegin();
priorityQ.erase(*priorityQ.rbegin());
if (added[now.b]) {
researchers += now.cost;
}
else {
PrimR(now.b, added);
}
}
}
int main()
{
int t;
// loop over all test cases
scanf("%d ", &t);
for (int i = 1; i <= t; i++) {
// read input nodes n, connections m
scanf("%d %d", &n, &m);
adj = new std::list<connection>[n];
//read connections and save them
for (int j = 0; j < m; j++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
addEdge(a - 1, b - 1, c);
}
researchers = 0;
// Use of prim with heaviest edges first
bool *added = new bool[n];
used = new std::list<int>[n];
for (int j = 0; j < n; j++) {
added[j] = false;
}
for (int j = 0; j < n; j++) {
if (!added[j]) {
Prim(j, added);
}
}
// print desired output
printf("Case #%d: %d\n", i, researchers);
delete[] adj;
delete[] added;
delete[] used;
}
return 0;
}
Do you know what I'm doing wrong?
I didn't consider, that between two nodes there could be multiple connections.
My following code solves this:
struct connection {
int a, b, cost, id;
bool operator<(const connection rhs) const {
return cost < rhs.cost || (cost == rhs.cost && id < rhs.id);
}
};
int n, m, researchers; // Amount of vertices, edges
std::list<connection> *adj; // Array of adjancency lists
std::set<connection> priorityQ;
void addEdge(int v, int w, int cost, int id) {
connection temp;
temp.a = v;
temp.b = w;
temp.cost = cost;
temp.id = id;
adj[v].push_back(temp);
temp.a = w;
temp.b = v;
adj[w].push_back(temp);
}
void deleteEdge(int v, int w, int id) {
for (std::list<connection>::iterator it = adj[v].begin(); it != adj[v].end(); ++it) {
if ((*it).id == id) {
adj[v].erase(it);
break;
}
}
for (std::list<connection>::iterator it = adj[w].begin(); it != adj[w].end(); ++it) {
if ((*it).id == id) {
adj[w].erase(it);
break;
}
}
}
void expand(int u) {
for (std::list<connection>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
connection v;
v.a = (*it).a < (*it).b ? (*it).a : (*it).b;
v.b = (*it).a < (*it).b ? (*it).b : (*it).a;
v.cost = (*it).cost;
v.id = (*it).id;
priorityQ.insert(v);
}
}
void PrimR(int u, bool added[]) {
added[u] = true;
expand(u);
}
// Prim algorithm
void Prim(int u, bool added[]) {
added[u] = true;
expand(u);
while (priorityQ.size() > 0) {
connection now = *priorityQ.rbegin();
priorityQ.erase(*priorityQ.rbegin());
deleteEdge(now.a, now.b, now.id);
if (added[now.b] && added[now.a]) {
researchers += now.cost;
}
else if (added[now.b]) {
PrimR(now.a, added);
}
else if (added[now.a]) {
PrimR(now.b, added);
}
}
}
int main()
{
int t;
// loop over all test cases
scanf("%d ", &t);
for (int i = 1; i <= t; i++) {
// read input nodes n, connections m
scanf("%d %d", &n, &m);
adj = new std::list<connection>[n];
//read connections and save them
for (int j = 0; j < m; j++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
addEdge(a - 1, b - 1, c, j);
}
researchers = 0;
// Use of prim with heaviest edges first
bool *added = new bool[n];
for (int j = 0; j < n; j++) {
added[j] = false;
}
for (int j = 0; j < n; j++) {
if (!added[j]) {
Prim(j, added);
}
}
// print desired output
printf("Case #%d: %d\n", i, researchers);
delete[] adj;
delete[] added;
}
return 0;
}
You can use Floyd-Warshall algorithm.
The Floyd-Warshall algorithm finds shortest path between all pairs of vertices.
And this shortest path to (u,u) -> (u,u) is the answer you're finding after considering every possible vertex u.
The algorithm run time is O(n^3).