#include <iostream>
#include <vector>

using namespace std; // Allows us to use standard library names without the std:: prefix

class Graph {
private:
    int V; // Number of vertices in the graph
    bool directed; // Indicates if the graph is directed
    vector<vector<int>> adjacencyMatrix; // 2D vector to store the adjacency matrix

public:
    // Constructor to initialize the graph
    Graph(int vertices, bool isDirected = false) : V(vertices), directed(isDirected) {
        // Resize the adjacency matrix to V x V and initialize all values to 0
        adjacencyMatrix.resize(V, vector<int>(V, 0));
    }

    // Method to add an edge from vertex u to vertex v with an optional weight
    void addEdge(int u, int v, int weight = 1) {
        adjacencyMatrix[u][v] = weight; // Set the weight for the edge from u to v
        if (!directed) {
            adjacencyMatrix[v][u] = weight; // For undirected graph, set the weight for the edge from v to u
        }
    }

    // Method to display the adjacency matrix
    void display() {
        // Iterate through each row of the adjacency matrix
        for (const auto& row : adjacencyMatrix) {
            // Print each value in the row
            for (int val : row) {
                cout << val << " ";
            }
            cout << endl; // Move to the next line after printing a row
        }
    }
};

int main() {
    // Create an undirected graph with 5 vertices
    Graph g(5, false);

    // Add edges to the undirected graph
    g.addEdge(0, 1);
    g.addEdge(0, 4);
    g.addEdge(1, 4);
    g.addEdge(1, 3);
    g.addEdge(3, 4);

    // Display the adjacency matrix for the undirected graph
    cout << "Adjacency Matrix for the Undirected Graph:" << endl;
    g.display();

    // Create a directed graph with 5 vertices
    Graph gDirected(5, true);

    // Add edges to the directed graph
    gDirected.addEdge(0, 1);
    gDirected.addEdge(1, 2);
    gDirected.addEdge(2, 0);
    gDirected.addEdge(3, 4);

    // Display the adjacency matrix for the directed graph
    cout << "\nAdjacency Matrix for the Directed Graph:" << endl;
    gDirected.display();

    return 0; // Indicate that the program ended successfully
}