#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
struct Edge {
int src, dest, weight;
bool operator<(const Edge& other) const {
return weight < other.weight;
}
};
class Graph {
public:
int V;
vector<Edge> edges;
Graph(int v) : V(v) {}
void addEdge(int src, int dest, int weight) {
Edge edge = {src, dest, weight};
edges.push_back(edge);
}
void primMST() {
vector<int> key(V, INT_MAX);
vector<int> parent(V, -1);
vector<bool> inMST(V, false);
key[0] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, 0});
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
inMST[u] = true;
for (const Edge& edge : edges) {
int v = (edge.src == u) ? edge.dest : edge.src;
int weight = edge.weight;
if (!inMST[v] && weight < key[v]) {
key[v] = weight;
parent[v] = u;
pq.push({key[v], v});
}
}
}
cout << "Prim MST:" << endl;
for (int i = 1; i < V; ++i)
cout << parent[i] << " - " << i << endl;
}
void kruskalMST() {
sort(edges.begin(), edges.end());
vector<int> parent(V, -1);
function<int(int)> find = [&](int i) {
while (parent[i] != -1)
i = parent[i];
return i;
};
function<void(int, int)> unionSets = [&](int x, int y) {
int rootX = find(x);
int rootY = find(y);
parent[rootX] = rootY;
};
cout << "Kruskal MST:" << endl;
for (const Edge& edge : edges) {
int rootSrc = find(edge.src);
int rootDest = find(edge.dest);
if (rootSrc != rootDest) {
cout << edge.src << " - " << edge.dest << endl;
unionSets(rootSrc, rootDest);
}
}
}
void dijkstra(int src) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
vector<int> dist(V, INT_MAX);
dist[src] = 0;
pq.push({0, src});
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
for (const Edge& edge : edges) {
if (edge.src == u) {
int v = edge.dest;
int weight = edge.weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
pq.push({dist[v], v});
}
}
}
}
cout << "Dijkstra Shortest Paths from vertex " << src << ":" << endl;
for (int i = 0; i < V; ++i)
cout << "To " << i << ": " << dist[i] << endl;
}
void bellmanFord(int src) {
vector<int> dist(V, INT_MAX);
dist[src] = 0;
for (int i = 1; i < V; ++i) {
for (const Edge& edge : edges) {
int u = edge.src;
int v = edge.dest;
int weight = edge.weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
}
}
}
for (const Edge& edge : edges) {
int u = edge.src;
int v = edge.dest;
int weight = edge.weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) {
cout << "Graph contains negative weight cycle!" << endl;
return;
}
}
cout << "Bellman-Ford Shortest Paths from vertex " << src << ":" << endl;
for (int i = 0; i < V; ++i)
cout << "To " << i << ": " << dist[i] << endl;
}
void floydWarshall() {
vector<vector<int>> dist(V, vector<int>(V, INT_MAX));
for (int i = 0; i < V; ++i)
dist[i][i] = 0;
for (const Edge& edge : edges)
dist[edge.src][edge.dest] = edge.weight;
for (int k = 0; k < V; ++k) {
for (int i = 0; i < V; ++i) {
for (int j = 0; j < V; ++j) {
if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX &&
dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
cout << "Floyd Shortest Paths:" << endl;
for (int i = 0; i < V; ++i) {
for (int j = 0; j < V; ++j) {
cout << dist[i][j] << "\t";
}
cout << endl;
}
}
};
int main() {
Graph g(6);
g.addEdge(0, 1, 4);
g.addEdge(0, 2, 3);
g.addEdge(1, 2, 1);
g.addEdge(1, 3, 2);
g.addEdge(2, 3, 4);
g.addEdge(3, 4, 2);
g.addEdge(4, 5, 6);
g.primMST();
g.kruskalMST();
g.dijkstra(0);
g.bellmanFord(0);
g.floydWarshall();
return 0;
}