結果
問題 |
No.1023 Cyclic Tour
|
ユーザー |
![]() |
提出日時 | 2025-05-14 12:59:48 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 7,909 bytes |
コンパイル時間 | 774 ms |
コンパイル使用メモリ | 81,300 KB |
実行使用メモリ | 14,208 KB |
最終ジャッジ日時 | 2025-05-14 13:00:58 |
合計ジャッジ時間 | 7,953 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 4 |
other | AC * 44 WA * 5 |
ソースコード
#include <iostream> #include <vector> #include <utility> // For std::pair using namespace std; // Global variables // Adjacency list representation of the graph. // Each element adj[u] is a vector of pairs {v, road_idx}, meaning there's a directed edge from u to v using road with index road_idx. vector<vector<pair<int, int>>> adj; // Stores the type of each road. road_type[i] = 1 if road i is bidirectional, 2 if unidirectional. vector<int> road_type; // Tracks the state of each vertex during DFS. // 0: white (not visited yet) // 1: gray (currently visiting, on the recursion stack) // 2: black (finished visiting this node and all its descendants) vector<int> visited; /** * @brief Performs Depth First Search (DFS) to detect cycles in the directed graph. * * This DFS implementation specifically handles the problem constraint: * A cycle formed by immediately traversing a bidirectional road back and forth * (e.g., u -> v -> u using the same bidirectional road i for both steps) is considered invalid. * Such a traversal is disallowed because it uses the same "road" twice. * * @param u The current vertex being visited. * @param incoming_road_idx The index of the road used to arrive at vertex u from its parent in the DFS tree. * This is crucial for detecting and correctly handling the forbidden length-2 cycles. * For the initial starting node of a DFS traversal, this value is -1. * @return true if a valid cycle (according to the problem rules) is detected starting from or passing through u, false otherwise. */ bool dfs(int u, int incoming_road_idx) { // Mark the current vertex u as gray, indicating it's currently being visited (on the recursion stack). visited[u] = 1; // Iterate through all outgoing edges from vertex u. for (auto& edge : adj[u]) { int v = edge.first; // The neighbor vertex connected by the current edge. int current_road_idx = edge.second; // The index of the road corresponding to the edge (u, v). // Check the state of the neighbor vertex v. if (visited[v] == 1) { // Case 1: The edge leads to a gray node v. // A gray node is currently on the recursion stack, meaning it's an ancestor of u in the DFS tree. // This indicates that we have found a back edge, which completes a cycle. // Now, we must check if this cycle is the specific forbidden type: // A length-2 cycle u -> v -> u using the same bidirectional road for both steps. // This condition holds if: // 1. The current road (u -> v) `current_road_idx` is bidirectional (road_type == 1). // 2. This road index `current_road_idx` is the same as the road index `incoming_road_idx` // which was used to travel from v to u to reach the current node u. // Check if road_type vector access is valid. road indices are 1..M. Vector indices are 0..M. // Since current_road_idx comes from input (1 to M), access road_type[current_road_idx] is safe. if (road_type[current_road_idx] == 1 && current_road_idx == incoming_road_idx) { // This is exactly the forbidden cycle configuration. // We should ignore this path and continue exploring other neighbors of u. continue; } else { // We have found a valid cycle. This cycle is either: // - Longer than length 2. // - Length 2 (u -> v -> u), but valid because: // - At least one of the edges (u, v) or (v, u) uses a unidirectional road. // - Both edges use bidirectional roads, but they are different roads (different indices). // In any case, a valid cycle exists. We can report true and terminate the search. return true; } } else if (visited[v] == 0) { // Case 2: The edge leads to a white node v. // A white node has not been visited yet in this DFS traversal. // We explore this node recursively. // We pass `current_road_idx` as the `incoming_road_idx` for the recursive call on v, // because this is the road used to reach v from u. if (dfs(v, current_road_idx)) { // If the recursive call `dfs(v, ...)` returns true, it means a cycle was found // somewhere down the path starting from v. We propagate this finding back up. return true; } } // Case 3: visited[v] == 2. The edge leads to a black node v. // A black node has been fully explored previously (either in the current DFS traversal or a prior one). // An edge to a black node signifies a cross edge or forward edge in the DFS tree structure. // Such edges do not form *new* cycles involving the current path back to an ancestor (gray node). // Therefore, we simply ignore this edge for the purpose of finding cycles involving the current path. } // After exploring all neighbors of u, if no cycle was found involving u through back edges, // mark u as black, indicating that the visit to u and its descendants is complete. visited[u] = 2; // Return false, indicating no cycle was found originating from or passing through u along the paths explored from this DFS call. return false; } int main() { // Use faster I/O operations standard in competitive programming. ios_base::sync_with_stdio(false); cin.tie(NULL); int N; // Number of cities (vertices) int M; // Number of roads (original edges) cin >> N >> M; // Initialize data structures. We use size N+1 and M+1 to allow for 1-based indexing used in the problem statement. adj.resize(N + 1); road_type.resize(M + 1); visited.resize(N + 1, 0); // Initialize all nodes as unvisited (white). // Read road information and build the directed graph representation using an adjacency list. for (int i = 1; i <= M; ++i) { int u, v, c; // Read vertices u, v connected by road i, and road type c. cin >> u >> v >> c; road_type[i] = c; // Store the type of road i (1 for bidirectional, 2 for unidirectional). if (c == 1) { // If road i is bidirectional, it allows travel in both directions. // Add a directed edge from u to v associated with road index i. adj[u].push_back({v, i}); // Add a directed edge from v to u associated with the same road index i. adj[v].push_back({u, i}); } else { // c == 2 // If road i is unidirectional, it allows travel only from u to v. // Add a directed edge from u to v associated with road index i. adj[u].push_back({v, i}); } } bool cycle_found = false; // Iterate through all vertices from 1 to N. // This loop ensures that we initiate DFS from each unvisited node, // covering all potentially disconnected components of the graph. for (int i = 1; i <= N; ++i) { // If vertex i has not been visited yet (is white). if (visited[i] == 0) { // Start a new DFS traversal from vertex i. // The initial call from the main loop doesn't have an incoming edge, so `incoming_road_idx` is -1. if (dfs(i, -1)) { // If the DFS call returns true, it means a valid cycle was found. cycle_found = true; // Since we only need to determine if *any* valid cycle exists, we can stop searching. break; } } } // Print the final result based on whether a cycle was found. if (cycle_found) { cout << "Yes" << endl; } else { cout << "No" << endl; } return 0; }