Teorema de paréntesis

El teorema de paréntesis se usa en DFS de gráfico . Establece que los descendientes en un árbol de búsqueda primero en profundidad tienen una propiedad interesante. Si v es un descendiente de u , entonces el tiempo de descubrimiento de v es posterior al tiempo de descubrimiento de u
En cualquier recorrido DFS de un gráfico g = (V, E), para dos vértices cualesquiera u y v se cumple exactamente uno de los siguientes: 

  • Los intervalos [d[u], f[u]] y [d[v], f[v]] son ​​completamente disjuntos y ni u ni v son descendientes del otro en el bosque de profundidad primero.
  • El intervalo [d[u], f[u]] está contenido dentro del intervalo [d[v], f[v]] , y u es un descendiente de v en un árbol de profundidad.
  • El intervalo [d[v], f[v]] está contenido completamente dentro del intervalo [d[u], f[u]] , y v es un descendiente de u en un árbol de profundidad.

Clasificación de bordes: el  
recorrido DFS se puede utilizar para clasificar los bordes del gráfico de entrada G = (V, E). Se pueden definir cuatro tipos de bordes en términos de un bosque primero en profundidad: 

  1. Tree Edge: Es un borde que está presente en el árbol obtenido después de aplicar DFS en el gráfico.
  2. Borde delantero: es un borde (u, v) tal que v es descendiente pero no forma parte del árbol DFS.
  3. Borde posterior: es un borde (u, v) tal que v es el ancestro del borde u pero no forma parte del árbol DFS. La presencia del borde posterior indica un ciclo en un gráfico dirigido.
  4. Cross Edge: Es un borde que conecta dos Nodes de tal manera que no tienen ningún antepasado y una relación descendiente entre ellos.

Dado un gráfico de N vértices y M aristas, la tarea es clasificar las aristas M en aristas de árbol, aristas delanteras, aristas traseras y aristas cruzadas .

Ejemplos:  

Entrada: N = 5, M = 7, arr[][] = { { 1, 2 }, { 1, 3 }, { 3, 4 }, { 1, 4 }, { 2, 5 }, { 5, 1 }, { 3, 2 } } } 
Salida: 
{1, 2} -> Borde del árbol 
{1, 3} -> Borde del árbol 
{3, 4} -> Borde del árbol 
{1, 4} -> Borde anterior 
{2 , 5} -> Borde del árbol 
{5, 1} -> Borde posterior 
{3, 2} -> Borde cruzado 
Explicación: 
1. Bordes verdes: Borde del árbol 
2. Bordes azules: Borde delantero 
3. Bordes negros: Borde trasero 
4. Bordes rojos: borde cruzado 
A continuación se muestra el gráfico dado para la información anterior: 
 

Entrada: N = 5, M = 4, arr[][] = { { 1, 2 }, { 1, 3 }, { 3, 4 }, { 1, 4 } } 
Salida: 
{1, 2} -> Borde del árbol 
{1, 3} -> Borde del árbol 
{3, 4} -> Borde del árbol 
{1, 4} -> Borde delantero 
Explicación: 
1. Bordes verdes: Borde del árbol 
2. Bordes azules: Borde delantero 
3. Bordes negros: Borde posterior 
4. Bordes rojos: borde cruzado 
A continuación se muestra el gráfico para la información anterior: 
 

Acercarse: 

  1. Use DFS Traversal en el gráfico dado para encontrar el tiempo de descubrimiento y el tiempo de finalización y el padre de cada Node.
  2. Usando el teorema de paréntesis, clasifique los bordes dados en las siguientes condiciones: 
    • Borde del árbol: para cualquier borde (U, V) , si el Node U es el padre del Node V, entonces (U, V) es el borde del árbol del gráfico dado.
    • Borde delantero: para cualquier borde (U, V) , si el tiempo de descubrimiento y el tiempo de finalización del Node V se superponen completamente con el tiempo de descubrimiento y el tiempo de finalización del Node U , entonces (U, V) es el borde delantero del gráfico dado.
    • Borde hacia atrás: para cualquier borde (U, V) , si el tiempo de descubrimiento y el tiempo de finalización del Node U se superponen completamente con el tiempo de descubrimiento y el tiempo de finalización del Node V , entonces (U, V) es el borde hacia atrás del gráfico dado.
    • Borde cruzado: para cualquier borde (U, V) , si el tiempo de descubrimiento y el tiempo de finalización del Node U no se superponen con el tiempo de descubrimiento y el tiempo de finalización del Node V , entonces (U, V) es el borde cruzado del gráfico dado.

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

C++

// C++ program for the above approach
 
#include "bits/stdc++.h"
using namespace std;
 
// For recording time
int tim = 0;
 
// For creating Graph
vector<list<int> > G;
 
// For calculating Discovery time
// and finishing time of nodes
vector<int> disc, fin;
 
// For finding Parent of node
vector<int> Par;
 
// For storing color of node
vector<char> Color;
 
// Recursive function for DFS
// to update the
void DFS_Visit(int v)
{
 
    // Make the current nodes as visited
    Color[v] = 'G';
 
    // Increment the time
    tim = tim + 1;
 
    // Assign the Discovery node of
    // node v
    disc[v] = tim;
 
    // Traverse the adjacency list of
    // vertex v
    for (auto& it : G[v]) {
 
        // If the nodes is not visited,
        // then mark the parent of the
        // current node and call DFS_Visit
        // for the current node
        if (Color[it] == 'W') {
            Par[it] = v;
            DFS_Visit(it);
        }
    }
    Color[v] = 'B';
    tim = tim + 1;
    fin[v] = tim;
}
 
void DFS(vector<list<int> >& G)
{
 
    // Initialise Par, disc, fin and
    // Color vector to size of graph
    Par.resize(G.size());
    disc.resize(G.size());
    fin.resize(G.size());
    Color.resize(G.size());
 
    // Initialise the Par[], Color[],
    // disc[], fin[]
    for (int i = 1; i < G.size(); i++) {
        Color[i] = 'W';
        Par[i] = 0;
        disc[i] = 0;
        fin[i] = 0;
    }
 
    // For every vertex if nodes is
    // not visited then call DFS_Visit
    // to update the discovery and
    // finishing time of the node
    for (int i = 1; i < G.size(); i++) {
 
        // If color is 'W', then
        // node is not visited
        if (Color[i] == 'W') {
            DFS_Visit(i);
        }
    }
}
 
// Function to check whether
// time intervals of x and y overlaps
// or not
bool checkOverlap(int x, int y)
{
 
    // Find the time intervals
    int x1 = disc[x], y1 = fin[x];
    int x2 = disc[y], y2 = fin[y];
 
    // Complete overlaps
    if (x2 > x1 && y1 > y2) {
        return true;
    }
    else {
        return false;
    }
}
 
// Function to check which Edges
// (x, y) belongs
string checkEdge(int x, int y)
{
 
    // For Tree Edge
    // If x is parent of y, then it
    // is Tree Edge
    if (Par[y] == x) {
        return "Tree Edge";
    }
 
    // For Forward Edge
    else if (checkOverlap(x, y)) {
        return "Forward Edge";
    }
 
    // For Backward Edge
    else if (checkOverlap(y, x)) {
        return "Backward Edge";
    }
 
    else {
        return "Cross Edge";
    }
}
 
// Function call to find the Tree Edge,
// Back Edge, Forward Edge, and Cross Edge
void solve(int arr[][2], int N, int M)
{
 
    // Create graph of N size
    G.resize(N + 1);
 
    // Traverse each edges
    for (int i = 0; i < M; i++) {
 
        int x = arr[i][0];
        int y = arr[i][1];
 
        // Make Directed graph
        G[x].push_back(y);
    }
 
    // DFS call to calculate discovery
    // and finishing time for each node
    DFS(G);
 
    // Condition for Tree Edge, Forward
    // Edges, Backward Edge and Cross Edge
    for (int i = 0; i < M; i++) {
 
        int x = arr[i][0];
        int y = arr[i][1];
 
        // Function call to check Edges
        cout << "{" << x << ", " << y
             << "} -> " << checkEdge(x, y)
             << endl;
    }
}
 
// Driver Code
int main()
{
 
    // Number of Nodes
    int N = 5;
 
    // Number of Edges
    int M = 7;
 
    // Edges for the graph
    int arr[M][2]
        = { { 1, 2 }, { 1, 3 },
            { 3, 4 }, { 1, 4 },
            { 2, 5 }, { 5, 1 },
            { 3, 1 } };
 
    // Function Call
    solve(arr, N, M);
 
    return 0;
}

Python3

# Python3 program for the above approach
 
# For recording time
tim = 0
 
# For creating Graph
G=[]
 
# For calculating Discovery time
# and finishing time of nodes
disc, fin=[],[]
 
# For finding Parent of node
Par=[]
 
# For storing color of node
Color=[]
 
# Recursive function for DFS
# to update the
def DFS_Visit(v):
    global tim
    # Make the current nodes as visited
    Color[v] = 'G'
 
    # Increment the time
    tim += 1
 
    # Assign the Discovery node of
    # node v
    disc[v] = tim
 
    # Traverse the adjacency list of
    # vertex v
    for it in G[v]:
 
        # If the nodes is not visited,
        # then mark the parent of the
        # current node and call DFS_Visit
        # for the current node
        if (Color[it] == 'W') :
            Par[it] = v
            DFS_Visit(it)
         
     
    Color[v] = 'B'
    tim = tim + 1
    fin[v] = tim
 
 
def DFS(G):
    global Par,disc,fin,Color
    # Initialise Par, disc, fin and
    # Color vector to size of graph
    Par=[-1]*len(G)
    disc=[-1]*len(G)
    fin=[-1]*len(G)
    Color=['']*len(G)
 
    # Initialise the Par[], Color[],
    # disc[], fin[]
    for i in range(1,len(G)):
        Color[i] = 'W'
        Par[i] = 0
        disc[i] = 0
        fin[i] = 0
     
 
    # For every vertex if nodes is
    # not visited then call DFS_Visit
    # to update the discovery and
    # finishing time of the node
    for i in range(1,len(G)):
 
        # If color is 'W', then
        # node is not visited
        if (Color[i] == 'W') :
            DFS_Visit(i)
         
     
 
 
# Function to check whether
# time intervals of x and y overlaps
# or not
def checkOverlap(x, y):
 
    # Find the time intervals
    x1 = disc[x]; y1 = fin[x]
    x2 = disc[y]; y2 = fin[y]
 
    # Complete overlaps
    if (x2 > x1 and y1 > y2) :
        return True
     
    else :
        return False
     
 
 
# Function to check which Edges
# (x, y) belongs
def checkEdge(x, y):
 
    # For Tree Edge
    # If x is parent of y, then it
    # is Tree Edge
    if (Par[y] == x) :
        return "Tree Edge"
     
 
    # For Forward Edge
    elif (checkOverlap(x, y)) :
        return "Forward Edge"
     
 
    # For Backward Edge
    elif (checkOverlap(y, x)) :
        return "Backward Edge"
     
 
    else :
        return "Cross Edge"
     
 
 
# Function call to find the Tree Edge,
# Back Edge, Forward Edge, and Cross Edge
def solve(arr, N, M):
    global G
    # Create graph of N size
    G=[[] for _ in range(N + 1)]
 
    # Traverse each edges
    for i in range(M):
 
        x = arr[i][0]
        y = arr[i][1]
 
        # Make Directed graph
        G[x].append(y)
     
 
    # DFS call to calculate discovery
    # and finishing time for each node
    DFS(G)
 
    # Condition for Tree Edge, Forward
    # Edges, Backward Edge and Cross Edge
    for i in range(M):
 
        x = arr[i][0]
        y = arr[i][1]
 
        # Function call to check Edges
        print("({0},{1})->".format(x,y),checkEdge(x, y))
     
 
 
# Driver Code
if __name__ == '__main__':
 
    # Number of Nodes
    N = 5
 
    # Number of Edges
    M = 7
 
    # Edges for the graph
    arr= [[1, 2] , [1, 3 ],
        [3, 4] , [1, 4 ],
        [2, 5] , [5, 1 ],
        [3, 1]] 
 
    # Function Call
    solve(arr, N, M)
Producción: 

{1, 2} -> Tree Edge
{1, 3} -> Tree Edge
{3, 4} -> Tree Edge
{1, 4} -> Forward Edge
{2, 5} -> Tree Edge
{5, 1} -> Backward Edge
{3, 1} -> Backward Edge

 

Complejidad temporal: O(N), donde N es el número total de Nodes en el gráfico.

Espacio Auxiliar: O(N)

Publicación traducida automáticamente

Artículo escrito por _mridul_bhardwaj_ 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 *