给定一个无向图G ,其顶点编号在[1,N]范围内,并且数组Edges [] []由M条边组成,任务是检查无向图的所有三元组是否都满足传递性。如果发现是真的,则打印“是” 。否则,打印“否” 。
Transitive property of an undirected graph states that:
If vertex X is connected to vertex Y, vertex Y is connected to vertex Z, then vertex X must be connected to the vertex Z.
例子:
Input: N = 4, M = 3 Edges[] = {{1, 3}, {3, 4}, {1, 4}}
Output: YES
Explanation:
Input : N = 4, M = 4, Edges[] = {{3, 1}, {2, 3}, {3, 4}, {1, 2}}
Output: NO
Explanation:
天真的方法:解决上述问题的最简单方法是遍历每个三元组的顶点(i,j,k) ,对于每个这样的三元组,如果i和j以及i和i在顶点j和k之间是否存在边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 )