Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions 4_graph_algorithms/Building_Roads.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
Problem: Building Roads
Category: Graph Algorithms (Undirected Graph)
Difficulty: Medium
Time Complexity: O(n + m)
Space Complexity: O(n + m)

Approach:
Use graph traversal to find connected components. Pick one representative node from each
component; the minimum number of roads required to connect all components is (components - 1).
Connect the representatives in a simple chain: (rep[0], rep[1]), (rep[1], rep[2]), ...

Key Insights:
- Any connected component can be represented by any one of its vertices.
- Connecting k components requires exactly k-1 edges; connecting representatives in a chain
achieves this minimum.
- Use iterative DFS (explicit stack) to avoid recursion-depth issues on large inputs.
- Handle edge cases: n = 1, m = 0, already connected graphs.

Notes:
- Nodes are 1-indexed (as per CSES problem statement).
- Fast I/O is used for competitive programming.
*/

#include <bits/stdc++.h>
using namespace std;

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

// Read number of cities (nodes) and existing roads (edges)
int num_nodes, num_edges;
if (!(cin >> num_nodes >> num_edges)) return 0;
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The input validation should handle the case where input fails more explicitly. Consider using proper error handling or removing this check entirely since competitive programming problems typically guarantee valid input.

Suggested change
if (!(cin >> num_nodes >> num_edges)) return 0;
cin >> num_nodes >> num_edges;

Copilot uses AI. Check for mistakes.

// Adjacency list for the undirected graph (1-indexed)
vector<vector<int>> adjacency(num_nodes + 1);
for (int i = 0; i < num_edges; ++i) {
int u, v;
cin >> u >> v;
// add both directions because graph is undirected
adjacency[u].push_back(v);
adjacency[v].push_back(u);
}

// visited[i] == true means node i has been visited in component discovery
vector<char> visited(num_nodes + 1, false);
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using vector<char> instead of vector<bool> is unconventional for boolean flags. Consider using vector<bool> which is specifically designed for boolean values and provides space optimization.

Suggested change
vector<char> visited(num_nodes + 1, false);
vector<bool> visited(num_nodes + 1, false);

Copilot uses AI. Check for mistakes.
// representatives: one node per connected component
vector<int> representatives;
representatives.reserve(num_nodes);

// Iterative DFS function using an explicit stack to avoid recursion depth limits
auto iterative_dfs = [&](int start) {
// stack for DFS traversal
std::stack<int> dfs_stack;
dfs_stack.push(start);
visited[start] = true;

while (!dfs_stack.empty()) {
int node = dfs_stack.top();
dfs_stack.pop();

// visit all neighbors
for (int neighbor : adjacency[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
dfs_stack.push(neighbor);
}
}
}
};

// Find connected components by scanning all nodes
for (int node = 1; node <= num_nodes; ++node) {
if (!visited[node]) {
// node is a new component representative
representatives.push_back(node);
// mark all nodes in this component as visited
iterative_dfs(node);
}
}

// Number of components
int component_count = static_cast<int>(representatives.size());

// Minimum roads required to connect all components = components - 1
int roads_to_add = max(0, component_count - 1);
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The max(0, component_count - 1) is unnecessary since component_count will always be at least 1 (when num_nodes >= 1). This can be simplified to component_count - 1.

Suggested change
int roads_to_add = max(0, component_count - 1);
int roads_to_add = component_count - 1;

Copilot uses AI. Check for mistakes.
cout << roads_to_add << '\n';

// Output the roads to add: connect consecutive representatives
for (int i = 0; i + 1 < component_count; ++i) {
cout << representatives[i] << ' ' << representatives[i + 1] << '\n';
}

return 0;
}