How to Count Connected Components That Form Cycles in an Undirected Graph?

I am working with an undirected graph and need to determine the number of connected components that are also cycles. A cycle is defined as a connected component where each vertex has exactly two edges, and the component contains at least three vertices.

The graph is represented by n vertices and m edges. Each edge connects two distinct vertices, and there are no duplicate edges.

Definitions:

  1. Undirected Graph:

    • Composed of two sets: one of vertices and the other of edges.
    • Each edge connects two distinct vertices (( u neq v )).
    • There is at most one edge between any pair of vertices.
  2. Connected Component:

    • A subset of vertices such that any two vertices in this subset are connected by a path, and the subset is not connected to any other vertex outside of it.
  3. Cycle:

    • A connected component is a cycle if:
      • It contains at least 3 vertices.
      • Each vertex is part of exactly 2 edges.
      • Rearranging its vertices can form a sequence such that the first vertex connects to the second, the second to the third, …, and the last vertex connects back to the first.

Input:

  • The first line contains two integers, n (1 ≤ n ≤ 200,000) and m (0 ≤ m ≤ 200,000), representing the number of vertices and edges.
  • The next m lines each contain two integers, u and v, describing an edge between vertex u and vertex v. There are no duplicate edges, and the graph is undirected.

Output:

  • A single integer: the number of connected components in the graph that are cycles.

Example:

Input:

17 15
1 8
1 12
5 11
11 9
9 15
15 5
4 13
3 13
4 3
10 16
7 10
16 7
14 3
14 4
17 6

Output:

2

My Attempt:

I implemented the following Python solution, which works for some cases but fails for certain hidden test cases in my university’s submission platform. Here’s the code I used:

from collections import defaultdict, deque

def count_cycle_components(n, m, edges):
    # Create an adjacency list for the graph
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)

    # Visited array to track visited nodes
    visited = [False] * (n + 1)

    # Helper function to check if a connected component is a cycle
    def is_cycle_component(node):
        queue = deque([(node, -1)])  # (current node, parent node)
        visited[node] = True
        node_count = 0
        edge_count = 0

        while queue:
            current, parent = queue.popleft()
            node_count += 1
            for neighbor in graph[current]:
                edge_count += 1
                if not visited[neighbor]:
                    visited[neighbor] = True
                    queue.append((neighbor, current))
                elif neighbor != parent:
                    pass  # Neighbor visited and not parent, ignore
        
        # Each edge is counted twice in an undirected graph
        edge_count //= 2

        # Check if the connected component is a cycle
        return node_count >= 3 and edge_count == node_count

    cycle_count = 0

    # Iterate through all nodes to find connected components
    for node in range(1, n + 1):
        if not visited[node]:
            if is_cycle_component(node):
                cycle_count += 1

    return cycle_count

if __name__ == "__main__":
    import sys
    input = sys.stdin.read
    data = input().splitlines()

    # Read the number of vertices and edges
    n, m = map(int, data[0].split())
    # Read the edges
    edges = [tuple(map(int, line.split())) for line in data[1:]]

    # Output the number of cycle components
    print(count_cycle_components(n, m, edges))

Any idea why does this code might fail for certain test cases? And how can it be corrected or optimized to fix this?

New contributor

אוהד גולדברג is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

1

Here’s an alternative method I’ve tried. I have implemented a DFS approach instead of BFS. And I’ve created a set for visited which prevents revisting nodes. These changes should improve the algorithm’s performance and ensure it passes all test cases. Let me know if it works.

from collections import defaultdict

def count_cycle_components(n, m, edges):
    # Create an adjacency list for the graph
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)

    visited = set()

    def is_cycle_component(node, parent):
        stack = [(node, parent)]
        component_nodes = set()
        edge_count = 0

        while stack:
            current, parent = stack.pop()
            if current in component_nodes:
                continue
            component_nodes.add(current)

            for neighbor in graph[current]:
                edge_count += 1
                if neighbor != parent:
                    stack.append((neighbor, current))

        # Each edge is counted twice in an undirected graph
        edge_count //= 2

        # Check if all nodes in the component have degree 2 and form a cycle
        if len(component_nodes) >= 3 and edge_count == len(component_nodes):
            for node in component_nodes:
                if len(graph[node]) != 2:
                    return False
            return True
        return False

    cycle_count = 0

    # Iterate through all nodes to find connected components
    for node in range(1, n + 1):
        if node not in visited:
            # Mark all nodes in the current component as visited
            component_nodes = set()
            stack = [node]
            while stack:
                current = stack.pop()
                if current not in visited:
                    visited.add(current)
                    component_nodes.add(current)
                    for neighbor in graph[current]:
                        if neighbor not in visited:
                            stack.append(neighbor)

            # Check if the connected component is a cycle
            if is_cycle_component(node, -1):
                cycle_count += 1

    return cycle_count

if __name__ == "__main__":
    import sys
    input = sys.stdin.read
    data = input().splitlines()

    n, m = map(int, data[0].split())
    edges = [tuple(map(int, line.split())) for line in data[1:]]
    print(count_cycle_components(n, m, edges))

New contributor

Pratyush Goutam is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

How to Count Connected Components That Form Cycles in an Undirected Graph?

I am working with an undirected graph and need to determine the number of connected components that are also cycles. A cycle is defined as a connected component where each vertex has exactly two edges, and the component contains at least three vertices.

The graph is represented by n vertices and m edges. Each edge connects two distinct vertices, and there are no duplicate edges.

Definitions:

  1. Undirected Graph:

    • Composed of two sets: one of vertices and the other of edges.
    • Each edge connects two distinct vertices (( u neq v )).
    • There is at most one edge between any pair of vertices.
  2. Connected Component:

    • A subset of vertices such that any two vertices in this subset are connected by a path, and the subset is not connected to any other vertex outside of it.
  3. Cycle:

    • A connected component is a cycle if:
      • It contains at least 3 vertices.
      • Each vertex is part of exactly 2 edges.
      • Rearranging its vertices can form a sequence such that the first vertex connects to the second, the second to the third, …, and the last vertex connects back to the first.

Input:

  • The first line contains two integers, n (1 ≤ n ≤ 200,000) and m (0 ≤ m ≤ 200,000), representing the number of vertices and edges.
  • The next m lines each contain two integers, u and v, describing an edge between vertex u and vertex v. There are no duplicate edges, and the graph is undirected.

Output:

  • A single integer: the number of connected components in the graph that are cycles.

Example:

Input:

17 15
1 8
1 12
5 11
11 9
9 15
15 5
4 13
3 13
4 3
10 16
7 10
16 7
14 3
14 4
17 6

Output:

2

My Attempt:

I implemented the following Python solution, which works for some cases but fails for certain hidden test cases in my university’s submission platform. Here’s the code I used:

from collections import defaultdict, deque

def count_cycle_components(n, m, edges):
    # Create an adjacency list for the graph
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)

    # Visited array to track visited nodes
    visited = [False] * (n + 1)

    # Helper function to check if a connected component is a cycle
    def is_cycle_component(node):
        queue = deque([(node, -1)])  # (current node, parent node)
        visited[node] = True
        node_count = 0
        edge_count = 0

        while queue:
            current, parent = queue.popleft()
            node_count += 1
            for neighbor in graph[current]:
                edge_count += 1
                if not visited[neighbor]:
                    visited[neighbor] = True
                    queue.append((neighbor, current))
                elif neighbor != parent:
                    pass  # Neighbor visited and not parent, ignore
        
        # Each edge is counted twice in an undirected graph
        edge_count //= 2

        # Check if the connected component is a cycle
        return node_count >= 3 and edge_count == node_count

    cycle_count = 0

    # Iterate through all nodes to find connected components
    for node in range(1, n + 1):
        if not visited[node]:
            if is_cycle_component(node):
                cycle_count += 1

    return cycle_count

if __name__ == "__main__":
    import sys
    input = sys.stdin.read
    data = input().splitlines()

    # Read the number of vertices and edges
    n, m = map(int, data[0].split())
    # Read the edges
    edges = [tuple(map(int, line.split())) for line in data[1:]]

    # Output the number of cycle components
    print(count_cycle_components(n, m, edges))

Any idea why does this code might fail for certain test cases? And how can it be corrected or optimized to fix this?

New contributor

אוהד גולדברג is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

1

Here’s an alternative method I’ve tried. I have implemented a DFS approach instead of BFS. And I’ve created a set for visited which prevents revisting nodes. These changes should improve the algorithm’s performance and ensure it passes all test cases. Let me know if it works.

from collections import defaultdict

def count_cycle_components(n, m, edges):
    # Create an adjacency list for the graph
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)

    visited = set()

    def is_cycle_component(node, parent):
        stack = [(node, parent)]
        component_nodes = set()
        edge_count = 0

        while stack:
            current, parent = stack.pop()
            if current in component_nodes:
                continue
            component_nodes.add(current)

            for neighbor in graph[current]:
                edge_count += 1
                if neighbor != parent:
                    stack.append((neighbor, current))

        # Each edge is counted twice in an undirected graph
        edge_count //= 2

        # Check if all nodes in the component have degree 2 and form a cycle
        if len(component_nodes) >= 3 and edge_count == len(component_nodes):
            for node in component_nodes:
                if len(graph[node]) != 2:
                    return False
            return True
        return False

    cycle_count = 0

    # Iterate through all nodes to find connected components
    for node in range(1, n + 1):
        if node not in visited:
            # Mark all nodes in the current component as visited
            component_nodes = set()
            stack = [node]
            while stack:
                current = stack.pop()
                if current not in visited:
                    visited.add(current)
                    component_nodes.add(current)
                    for neighbor in graph[current]:
                        if neighbor not in visited:
                            stack.append(neighbor)

            # Check if the connected component is a cycle
            if is_cycle_component(node, -1):
                cycle_count += 1

    return cycle_count

if __name__ == "__main__":
    import sys
    input = sys.stdin.read
    data = input().splitlines()

    n, m = map(int, data[0].split())
    edges = [tuple(map(int, line.split())) for line in data[1:]]
    print(count_cycle_components(n, m, edges))

New contributor

Pratyush Goutam is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật