Comprobar la propiedad transitiva en un gráfico no dirigido dado

Dado un grafo no dirigido G con vértices numerados en el rango [1, N] y una array Aristas[][] que consta de M aristas, la tarea es verificar si todos los tripletes del grafo no dirigido satisfacen la propiedad transitiva o no. Si se encuentra que es cierto, escriba «SÍ» . De lo contrario, escriba “NO” .

La propiedad transitiva de un grafo no dirigido establece que:
Si el vértice X está conectado al vértice Y , el vértice Y está conectado al vértice Z , entonces el vértice X debe estar conectado al vértice Z.

Ejemplos:

Entrada: N = 4, M = 3 Bordes[] = {{1, 3}, {3, 4}, {1, 4}}
Salida: SÍ 
Explicación:

Entrada: N = 4, M = 4, Bordes[] = {{3, 1}, {2, 3}, {3, 4}, {1, 2}}
Salida : NO 
Explicación:

Enfoque ingenuo: el enfoque más simple para resolver el problema anterior es atravesar cada triplete de vértices (i, j, k) y, para cada triplete, verificar si hay un borde entre los vértices j y k si i y j , y i y k están conectados directamente por un borde con la ayuda de una array de adyacencia. 

Complejidad de Tiempo: O(N 3 )
Espacio Auxiliar: O(N 2 )

Enfoque eficiente: la idea es encontrar todos los componentes conectados presentes en el gráfico . Finalmente, verifique si todos los componentes conectados del gráfico son un gráfico completo o no. Si se encuentra que es cierto, escriba «SÍ» . De lo contrario, escriba “NO” . Siga los pasos a continuación para resolver el problema:

  • Representa el gráfico, G en forma de lista de adyacencia .
  • Encuentre todas las componentes conexas del gráfico y verifique si la componente conexa es un gráfico completo o no realizando las siguientes operaciones: 
    • Encuentre el recuento total de vértices en el gráfico conectado actual, por ejemplo, X .
    • Si todos los vértices del componente conectado no están conectados a X – 1 vértices, imprima «NO» .
  • Finalmente, verifique si todos los componentes conectados son un gráfico completo o no. SI se encuentra que es cierto, escriba «SÍ» .

A continuación se muestra la implementación del enfoque anterior:

C++

// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Stores undirected graph using
// adjacency list representation
class Graph {
 
    // Stores count of vertices
    int V;
 
    // adj[i]: Store all the nodes
    // connected to i
    list<int>* adj;
 
    // DFS function
    void DFSUtil(int v, bool visited[], int id[],
                 int id_number, int& c);
 
public:
    Graph(int V);
    ~Graph();
 
    // Connect two vertices v and w
    void addEdge(int v, int w);
 
    // Check if the connected component
    // is a complete graph or not
    bool connectedComponents();
};
 
Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V + 1];
}
 
// Destructor
Graph::~Graph() { delete[] adj; }
 
// Function to add an undirected
// edge between two vertices
void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w);
    adj[w].push_back(v);
}
 
// Function to find all the connected
// components of a graph using DFS
void Graph::DFSUtil(int v, bool visited[], int id[],
                    int id_number, int& c)
{
 
    // Mark the vertex v as visited
    visited[v] = true;
 
    // Assign an id of current
    // connected component
    id[v] = id_number;
 
    // Increase the count of vertices in
    // current connected component
    c++;
 
    // Recursively call for all the
    // vertices adjacent to this vertex
    list<int>::iterator i;
 
    // Iterate over all the adjacent
    // vertices of the current vertex
    for (i = adj[v].begin(); i != adj[v].end();
         ++i) {
 
        // If current vertex is not visited
        if (!visited[*i])
            DFSUtil(*i, visited, id,
                    id_number, c);
    }
}
 
// Function to find connected
// components of the graph
bool Graph::connectedComponents()
{
 
    bool* visited = new bool[V + 1];
 
    // id[i]: Stores an unique id of connected
    // component in which vertex i exists
    int* id = new int[V + 1];
 
    // Store count of nodes in current
    // connected component
    int* component_size = new int[V + 1];
 
    // Mark all the vertices as not visited
    for (int v = 1; v <= V; v++)
        visited[v] = false;
 
    for (int v = 1; v <= V; v++) {
 
        // If vertex v is not marked
        if (visited[v] == false) {
 
            // Stores the size of a component
            // in which vertex v lies
            int c = 0;
 
            // Stores id of current
            // connected component
            int id_number = v;
 
            DFSUtil(v, visited, id,
                    id_number, c);
 
            // Stores count of vertices of
            // current component
            component_size[v] = c;
        }
        else {
 
            component_size[v]
                = component_size[id[v]];
        }
    }
 
    // Iterate over all the vertices
    for (int v = 1; v <= V; v++) {
 
        // IF connected component[v] is
        // not a complete graph
        if (component_size[v] - 1
            != (int)adj[v].size()) {
 
            delete[] visited;
            return false;
        }
    }
 
    delete[] visited;
    return true;
}
 
// Function to check if graph is
// Edge Transitive or not
void isTransitive(int N, int M,
                  vector<vector<int> > Edge)
{
 
    // Initialize a graph
    Graph G(N);
 
    // Traverse the array Edge[]
    for (int i = 0; i < M; i++) {
        G.addEdge(Edge[i][0], Edge[i][1]);
    }
 
    // If all the connected components
    // are a complete graph
    int f = G.connectedComponents();
    if (f == 0) {
        cout << "NO\n";
    }
    else {
        cout << "YES\n";
    }
}
 
// Driver Code
int main()
{
    // Input
    int N = 4, M = 3;
    vector<vector<int> > Edge{ { 1, 3 },
                               { 3, 4 },
                               { 1, 4 } };
    isTransitive(N, M, Edge);
 
    return 0;
}

Python3

# Python3 program of the above approach
 
# Function to add an undirected
# edge between two vertices
def addEdge(v, w):
    global adj
    adj[v].append(w)
    adj[w].append(v)
 
# Function to find all the connected
# components of a graph using DFS
def DFSUtil(v, id, id_number):
    global visited, adj, c
 
    # Mark the vertex v as visited
    visited[v] = True
 
    # Assign an id of current
    # connected component
    id[v] = id_number
 
    # Increase the count of vertices in
    # current connected component
    c += 1
 
    # Iterate over all the adjacent
    # vertices of the current vertex
    for i in adj[v]:
       
        # If current vertex is not visited
        if (not visited[i]):
            DFSUtil(i, id, id_number)
 
# Function to find connected
# components of the graph
def connectedComponents():
    global V, adj, visited, c
 
    # id[i]: Stores an unique id of connected
    # component in which vertex i exists
    id = [0]*(V + 1)
 
    # Store count of nodes in current
    # connected component
    component_size = [0]*(V + 1)
    for v in range(1, V + 1):
 
        # If vertex v is not marked
        if (visited[v] == False):
 
            # Stores the size of a component
            # in which vertex v lies
            c = 0
 
            # Stores id of current
            # connected component
            id_number = v
            DFSUtil(v, id, id_number)
 
            # Stores count of vertices of
            # current component
            component_size[v] = c
        else:
 
            component_size[v] = component_size[id[v]]
 
    # Iterate over all the vertices
    for v in range(1, V + 1):
 
        # IF connected component[v] is
        # not a complete graph
        if (component_size[v] - 1 != len(adj[v])):
            return False
    return True
 
# Function to check if graph is
# Edge Transitive or not
def isTransitive(N, M, Edge):
    global adj, visited, c
 
    # Traverse the array Edge[]
    for i in range(M):
        addEdge(Edge[i][0], Edge[i][1])
 
    # If all the connected components
    # are a complete graph
    f = connectedComponents()
    if (f == 0):
        print("NO")
    else:
        print("YES")
 
# Driver Code
if __name__ == '__main__':
     
    # Input
    V, c = 5, 0
    adj = [[] for i in range(V + 1)]
    visited = [False] * (V + 1)
 
    N, M = 4, 3
    Edge = [ [ 1, 3 ],
           [ 3, 4 ],
           [ 1, 4 ] ]
    isTransitive(N, M, Edge)
 
    # This code is contributed by mohit kumar 29
Producción: 

YES

 

Complejidad temporal: O(N + M)
Espacio auxiliar: O(N 2 )

Publicación traducida automáticamente

Artículo escrito por kapil16garg y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *