📜  检查给定无向图中的传递性

📅  最后修改于: 2021-04-17 15:48:52             🧑  作者: Mango

给定一个无向图G ,其顶点编号在[1,N]范围内,并且数组Edges [] []M条边组成,任务是检查无向图的所有三元组是否都满足传递性。如果发现是真的,则打印“是” 。否则,打印“否”

例子:

天真的方法:解决上述问题的最简单方法是遍历每个三元组的顶点(i,j,k) ,对于每个这样的三元组,如果ij以及i和i在顶点jk之间是否存在边k和k在邻接矩阵的帮助下通过边直接连接。
时间复杂度: O(N 3 )
辅助空间: O(N 2 )

高效方法:想法是找到图中存在的所有连接组件。最后,检查图的所有连接组件是否都是完整的图。如果发现是真的,则打印“是” 。否则,打印“否” 。请按照以下步骤解决问题:

  • 以邻接表的形式表示图G。
  • 查找图形的所有连接的组件,并通过执行以下操作来检查连接的组件是否是完整的图形:
    • 在当前连接的图中找到顶点的总数X。
    • 如果连接的组件的所有顶点均未连接到X – 1个顶点,则打印“否”
  • 最后,检查所有连接的组件是否都是完整的图形。如果发现是真的,则打印“是”

下面是上述方法的实现:

C++
// C++ program of the above approach
#include 
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* adj;
 
    // DFS fucntion
    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 componenet
    // is a compleate graph or not
    bool connectedComponents();
};
 
Graph::Graph(int V)
{
    this->V = V;
    adj = new list[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 componenet
    id[v] = id_number;
 
    // Increase the count of vertices in
    // current connected componenet
    c++;
 
    // Recursively call for all the
    // vertices adjacent to this vertex
    list::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 connnected
// componenets 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 compleate 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 > 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 compleate 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 > 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 componenet
    id[v] = id_number
 
    # Increase the count of vertices in
    # current connected componenet
    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 connnected
# componenets 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 compleate 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 compleate 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


输出:
YES

时间复杂度: O(N + M)
辅助空间: O(N 2 )