Nabil Mohammed
Nabil Mohammed
Nabil Mohammed
NAME ID NO
NABIL MOHAMMED………………………..UGR/51354/13
c++
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100001
#define INF 1000000000
int n, m;
vector<pair<int, int>> adj[MAXN];
bool visited[MAXN];
int dist[MAXN];
int prim() {
// Initialize the distances to infinity and visited to false
for (int i = 1; i <= n; i++) {
dist[i] = INF;
visited[i] = false;
}
// Initialize the priority queue with the source vertex
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push(make_pair(0, 1)); // (distance, vertex)
dist[1] = 0;
int ans = 0;
// Iterate until the priority queue is empty
while (!pq.empty()) {
// Pop the vertex with the smallest distance from the priority queue
int u = pq.top().second;
pq.pop();
// Skip if vertex is already visited
if (visited[u]) continue;
visited[u] = true;
ans += dist[u];
// Iterate through all adjacent vertices
for (auto v : adj[u]) {
// If the vertex is not visited and the edge has smaller weight, update the
distance and add to the priority queue
if (!visited[v.first] && dist[v.first] > v.second) {
dist[v.first] = v.second;
pq.push(make_pair(dist[v.first], v.first));
}
}
}
return ans;
}
int main() {
cin >> n >> m; // Number of vertices, number of edges
// Read in the graph
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back(make_pair(v, w));
adj[v].push_back(make_pair(u, w));
}
// Call the Prim's algorithm function and output the result
cout << prim() << "\n";
return 0;
}
The time complexity of Prism's algorithm is O(E log V) using the priority queue.
Kruskal's algorithm is another greedy algorithm that finds a minimum spanning tree for a
weighted undirected graph. The algorithm operates by sorting all the edges in increasing order
of their weight, and then adding them to the MST one at a time, as long as they do not create a
cycle.
Here's the implementation of Kruskal's algorithm in iterative form in C++:
#include<bits/stdc++.h>
using namespace std;
vector<int> parent(V);
for (int i = 0; i < V; i++)
parent[i] = i;
int cnt = 0;
for (auto it : edges)
{
int u = it.second.first;
int v = it.second.second;
int set_u = parent[u];
int set_v = parent[v];
if (set_u != set_v)
{
cout << u << " - " << v << endl;
mst_wt += it.first;
cnt++;
for(int i=0;i<V;i++)
{
if(parent[i]==set_v)
{
parent[i]=set_u;
}
}
}
if(cnt==V-1)
break;
}
return mst_wt;
}
int main()
{
int V = 5, E = 7;
Graph g(V, E);
g.addEdge(0, 1, 2);
g.addEdge(0, 3, 6);
g.addEdge(1, 2, 3);
g.addEdge(1, 3, 8);
g.addEdge(1, 4, 5);
g.addEdge(2, 4, 7);
g.addEdge(3, 4, 9);
return 0;
}
The time complexity of this algorithm can be O(ElogE) or O(ElogV), depending on how we
implement the sorting of edges.
The total time complexity of Kruskal's algorithm is O(ElogE + ElogV) or O(ElogE + E) depending
on the implementation of sorting.
//ElogE for sorting E edges in edge_list
//ElogV for applying FIND & UNION operations on E edges having V vertices
The implementation of Dijkstra's algorithm
Dijkstra's algorithm is another popular graph algorithm used to find the shortest path from a
single source vertex to all other vertices in a graph with non-negative edge weights. The
algorithm operates by maintaining a set of visited vertices and distances from the source vertex
to all other vertices. At each iteration, it selects the vertex with the smallest distance from the
source vertex that has not been visited, updates the distances of its neighbors if a shorter path
can be found, and adds it to the set of visited vertices.
c++
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100001
#define INF 1000000000
int n, m;
vector<pair<int, int>> adj[MAXN];
int dist[MAXN];
bool visited[MAXN];
int dijkstra(int s) {
// Initialize distances to infinity and visited to false
for (int i = 1; i <= n; i++) {
dist[i] = INF;
visited[i] = false;
}
// Initialize the priority queue with the source vertex
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push(make_pair(0, s)); // (distance, vertex)
dist[s] = 0;
// Iterate until the priority queue is empty
while (!pq.empty()) {
// Pop the vertex with the smallest distance from the priority queue
int u = pq.top().second;
pq.pop();
// Skip if vertex is already visited
if (visited[u]) continue;
visited[u] = true;
// Iterate through all adjacent vertices
for (auto v : adj[u]) {
// If the vertex is not visited and the distance can be updated, update the
distance and add to the priority queue
if (!visited[v.first] && dist[v.first] > dist[u] + v.second) {
dist[v.first] = dist[u] + v.second;
pq.push(make_pair(dist[v.first], v.first));
}
}
}
return dist[n];
}
int main() {
cin >> n >> m; // Number of vertices, number of edges
// Read in the graph as an adjacency list with weights
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back(make_pair(v, w));
adj[v].push_back(make_pair(u, w)); // Add both directions for an undirected
graph
}
// Call the Dijkstra's algorithm function with source vertex 1 and output the result
cout << dijkstra(1) << "\n";
return 0;
}
The time complexity of Dijkstra's algorithm is O(VlogV + ElogV) or simply O((V + E)logV), where
E is the number of edges in the graph.
However, if we use an adjacency list to represent the graph and a binary heap to implement the
priority queue, then the time complexity of Dijkstra's algorithm becomes O((V+E)logV), which is
faster than that of using a Fibonacci heap.