結果
問題 |
No.1776 Love Triangle 2 (Hard)
|
ユーザー |
![]() |
提出日時 | 2025-05-14 12:56:18 |
言語 | PyPy3 (7.3.15) |
結果 |
TLE
|
実行時間 | - |
コード長 | 6,853 bytes |
コンパイル時間 | 416 ms |
コンパイル使用メモリ | 82,780 KB |
実行使用メモリ | 85,868 KB |
最終ジャッジ日時 | 2025-05-14 12:58:47 |
合計ジャッジ時間 | 12,734 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 4 TLE * 1 -- * 171 |
ソースコード
import sys # Increase recursion depth limit for deep searches that might occur with path lengths up to N. # N can be up to 150. Setting limit to N + buffer, e.g., 200 or higher. # Using 2000 as a safe large value. try: sys.setrecursionlimit(2000) except Exception as e: # Some platforms might restrict changing recursion depth. Proceed anyway. # Might raise RecursionError if path length exceeds default limit. # print(f"Warning: Could not set recursion depth: {e}", file=sys.stderr) pass def solve(): # Read N (number of students) and M (number of friendships) N, M = map(int, sys.stdin.readline().split()) # Read the three special students X, Y, Z X, Y, Z = map(int, sys.stdin.readline().split()) # Initialize adjacency matrix for the friendship graph G. # adj[u][v] = True if u and v are friends. # Size (N+1)x(N+1) to use 1-based indexing conveniently. adj = [[False] * (N + 1) for _ in range(N + 1)] for _ in range(M): u, v = map(int, sys.stdin.readline().split()) adj[u][v] = True adj[v][u] = True # Friendships are mutual (undirected graph) # Precompute the adjacency list for the complement graph G_bar. # An edge (u, v) exists in G_bar if u and v are NOT friends. # Store neighbors for each node in a list. non_friend_adj = [[] for _ in range(N + 1)] for i in range(1, N + 1): for j in range(1, N + 1): # Check if i and j are different nodes and are not friends if i != j and not adj[i][j]: non_friend_adj[i].append(j) # Sort the neighbor lists for G_bar. This is crucial for ensuring that # when we explore paths, we do so in an order that guarantees finding # the lexicographically smallest path first. for i in range(1, N + 1): non_friend_adj[i].sort() # Variables to store the result: minimum cycle length k and the path itself. best_k = -1 best_path = [] # State variables for the Depth First Search (DFS) visited = [False] * (N + 1) # Keep track of nodes visited in the current path path = [] # Store the nodes in the current path being explored # Recursive DFS function to find a cycle of a specific length k_target def find_cycle_recursive(curr_node, k_target): # Declare that we intend to modify these variables defined in the outer scope nonlocal best_k, best_path # Add the current node to the path and mark it as visited path.append(curr_node) visited[curr_node] = True current_len = len(path) # Base Case: If the path length reaches the target length k_target if current_len == k_target: # Check two conditions for a valid cycle: # 1. The last node in the path (curr_node) must be able to connect back to the starting node X. # This means curr_node and X must NOT be friends (edge exists in G_bar). # 2. The required students Y and Z must be included in the path. # Check connection back to X if not adj[curr_node][X]: # Check inclusion of Y and Z using the visited array (efficient) if visited[Y] and visited[Z]: # Found a valid cycle that satisfies all conditions! best_k = k_target # Construct the final path representation: start node X, followed by path nodes, ending with X. # The 'path' list currently contains nodes from X up to curr_node. # We need to copy it and append X at the end for the output format. best_path = path[:] + [X] # Backtrack state correctly before returning True to signal success visited[curr_node] = False path.pop() return True # Cycle found # If either condition fails (cannot connect back to X, or Y/Z missing), backtrack state visited[curr_node] = False path.pop() return False # Cycle not valid or incomplete, continue search # Recursive Step: Explore neighbors of the current node # Iterate through neighbors in the complement graph G_bar # The neighbors list is already sorted, ensuring lexicographical exploration for next_node in non_friend_adj[curr_node]: # Explore neighbor only if it has not been visited in the current path # This prevents cycles within the path (ensures simple path) if not visited[next_node]: # Make the recursive call for the neighbor if find_cycle_recursive(next_node, k_target): # If the recursive call returns True, it means a cycle was found down that path. # We need to propagate this True result upwards. # Important: Backtrack the state of the current node before returning. visited[curr_node] = False path.pop() return True # Signal cycle found # If no cycle was found through any neighbor of curr_node, backtrack state visited[curr_node] = False path.pop() return False # No cycle found from this path branch # Main part of the algorithm: Iterate through possible cycle lengths k # Start from k=3 (minimum possible cycle length) up to N (maximum possible). for k in range(3, N + 1): # Reset the visited array and path list for the search with the new length k # Clearing the visited array directly is faster than creating a new one each time. for i in range(1, N + 1): visited[i] = False path = [] # Reset the path list # Start the DFS search from the designated starting node X if find_cycle_recursive(X, k): # If find_cycle_recursive returns True, it means a cycle of length k was found. # Since we iterate k in increasing order, the first k for which we find a cycle is the minimum k. # And because we explore neighbors in sorted order, the first cycle found for this minimum k # is guaranteed to be the lexicographically smallest one. # Therefore, we can stop the search immediately. break # After checking all possible lengths k, output the result. if best_k != -1: # A valid cycle was found print(best_k) # Output the minimum length k print(*(best_path)) # Output the lexicographically smallest path (nodes separated by spaces) else: # No valid cycle was found for any length k print("-1") # Execute the main function to solve the problem solve()