Skip to main content

Your First Problem

Let’s solve a classic shortest path problem using the Dijkstra algorithm snippet. This guide will walk you through a complete example from template to solution.

Problem Statement

Given a weighted graph with n nodes and m edges, find the shortest distance from a source node to all other nodes. Input:
  • First line: n (number of nodes), m (number of edges)
  • Next m lines: u v w (edge from u to v with weight w)
  • Last line: s (source node)
Output:
  • n space-separated integers representing shortest distances from source

Building the Solution

1

Start with a Template

Create a new file solution.cpp and type template_std then trigger autocomplete:
/**
 * @created     : March 05, 2026
 * @handle      : @LuchoBazz
 */

#include <bits/stdc++.h>

using namespace std;

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    
    return 0;
}
The ios_base::sync_with_stdio(0) and cin.tie(0) optimize I/O operations for competitive programming.
2

Add Graph Structure

Before main(), type graph_graph to add the base graph structure:
template <typename T>
struct edge {
    int from;
    int to;
    T cost;
};

template <typename T>
struct link {
    int to;
    T cost;
    bool operator>(const link& other) const {return cost > other.cost;}
    bool operator<(const link& other) const {return cost < other.cost;}
};

template <typename T>
class graph {
public:
    vector<edge<T>> edges;
    vector<vector<link<T>>> adj;
    int n;
    graph(int sz) : n(sz) {
        adj.resize(n);
    }
    virtual void add(int from, int to, T cost) = 0;
};
3

Add Directed Graph Implementation

Type graph_digraph to add the directed graph class:
template <typename T>
class digraph : public graph<T> {
public:
    using graph<T>::edges;
    using graph<T>::adj;
    using graph<T>::n;

    digraph(int sz) : graph<T>(sz) {}

    void add(int from, int to, T cost = 1) {
        assert(0 <= from && from < n && 0 <= to && to < n);
        edges.push_back({from, to, cost});
        adj[from].push_back({to, cost});
    }
};
Use graph_undigraph for undirected graphs instead.
4

Add Dijkstra Algorithm

Type graph_dijkstra_std to add the Dijkstra implementation:
template <typename T>
vector <T> dijkstra(const graph<T> &g, int start) {
    assert(0 <= start && start < g.n);
    priority_queue<link<T>, vector<link<T>>, greater<link<T>>> Q;
    vector<T> dist(g.n, numeric_limits<T>::max());
    dist[start] = static_cast<T>(0);
    Q.push({start, static_cast<T>(0)});
    while (!Q.empty()) {
        link<T> node = Q.top(); Q.pop();
        int to = node.to;
        if(node.cost > dist[to]) {
            continue;
        }
        for (link<T> neighbor: g.adj[to]) {
            T newCost = dist[to] + neighbor.cost;
            if (newCost < dist[neighbor.to]) {
                Q.push({neighbor.to, newCost});
                dist[neighbor.to] = newCost;
            }
        }
    }
    return dist;
    // returns numeric_limits<T>::max() if there's no path
}
5

Complete the Solution

Add the main logic to read input and call the algorithm:
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    
    int n, m;
    cin >> n >> m;
    
    digraph<int> g(n);
    
    for(int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        g.add(u, v, w);
    }
    
    int source;
    cin >> source;
    
    vector<int> dist = dijkstra(g, source);
    
    for(int i = 0; i < n; i++) {
        if(dist[i] == numeric_limits<int>::max()) {
            cout << "INF";
        } else {
            cout << dist[i];
        }
        if(i < n - 1) cout << " ";
    }
    cout << endl;
    
    return 0;
}

Complete Solution

Here’s the final solution combining all snippets:
solution.cpp
/**
 * @created     : March 05, 2026
 * @handle      : @LuchoBazz
 */

#include <bits/stdc++.h>

using namespace std;

template <typename T>
struct edge {
    int from;
    int to;
    T cost;
};

template <typename T>
struct link {
    int to;
    T cost;
    bool operator>(const link& other) const {return cost > other.cost;}
    bool operator<(const link& other) const {return cost < other.cost;}
};

template <typename T>
class graph {
public:
    vector<edge<T>> edges;
    vector<vector<link<T>>> adj;
    int n;
    graph(int sz) : n(sz) {
        adj.resize(n);
    }
    virtual void add(int from, int to, T cost) = 0;
};

template <typename T>
class digraph : public graph<T> {
public:
    using graph<T>::edges;
    using graph<T>::adj;
    using graph<T>::n;

    digraph(int sz) : graph<T>(sz) {}

    void add(int from, int to, T cost = 1) {
        assert(0 <= from && from < n && 0 <= to && to < n);
        edges.push_back({from, to, cost});
        adj[from].push_back({to, cost});
    }
};

template <typename T>
vector <T> dijkstra(const graph<T> &g, int start) {
    assert(0 <= start && start < g.n);
    priority_queue<link<T>, vector<link<T>>, greater<link<T>>> Q;
    vector<T> dist(g.n, numeric_limits<T>::max());
    dist[start] = static_cast<T>(0);
    Q.push({start, static_cast<T>(0)});
    while (!Q.empty()) {
        link<T> node = Q.top(); Q.pop();
        int to = node.to;
        if(node.cost > dist[to]) {
            continue;
        }
        for (link<T> neighbor: g.adj[to]) {
            T newCost = dist[to] + neighbor.cost;
            if (newCost < dist[neighbor.to]) {
                Q.push({neighbor.to, newCost});
                dist[neighbor.to] = newCost;
            }
        }
    }
    return dist;
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    
    int n, m;
    cin >> n >> m;
    
    digraph<int> g(n);
    
    for(int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        g.add(u, v, w);
    }
    
    int source;
    cin >> source;
    
    vector<int> dist = dijkstra(g, source);
    
    for(int i = 0; i < n; i++) {
        if(dist[i] == numeric_limits<int>::max()) {
            cout << "INF";
        } else {
            cout << dist[i];
        }
        if(i < n - 1) cout << " ";
    }
    cout << endl;
    
    return 0;
}

Testing the Solution

Sample Input

5 6
0 1 4
0 2 1
2 1 2
1 3 1
2 3 5
3 4 3
0

Expected Output

0 3 1 4 7

Compile and Run

g++ -std=c++17 -O2 -o solution solution.cpp
./solution < input.txt
Use the -DDEBUG flag during development to enable debug macros from misc_debug:
g++ -std=c++17 -O2 -DDEBUG -o solution solution.cpp

Competitive Programming Workflow

Efficient Snippet Usage

  1. Start Fast: Use template_std or competition-specific templates like template_google or template_usaco
  2. Build Incrementally: Add only the snippets you need for the problem
  3. Test Quickly: Use template_random to generate test cases
  4. Debug Efficiently: Add misc_debug when you need detailed output

Common Snippet Combinations

template_std
+ graph_graph
+ graph_digraph (or graph_undigraph)
+ graph_dijkstra_std (or other graph algorithm)
template_std
+ range_query_segment_tree
(or range_query_fenwick_tree_std)
template_std
+ string_kmp_std
(or string_hashing_static_compress)
template_std
+ numeric_mint_compress
+ combinatorics_ncr_compress

Pro Tips

Use Template Headers

template_header provides optimized pragmas and common macros:
  • Compiler optimizations with #pragma GCC
  • Shortened macros: PB, SZ, all, rall
  • Loop macros: forn, rof

Debug Smartly

misc_debug provides comprehensive debug output:
  • Works with vectors, maps, sets, pairs
  • Only compiles when -DDEBUG flag is set
  • Use log(variable) to print

Handle Multiple Test Cases

Use template_cases for problems with multiple test cases:
  • Automatic case numbering
  • Clean structure for T test cases

Fast I/O Operations

All templates include fast I/O:
  • ios_base::sync_with_stdio(0)
  • cin.tie(0)
  • Critical for large input problems

Next Steps

Snippet Usage

Learn advanced snippet triggers and editor configuration

Available Templates

Explore all available template options

Competitive Programming

Master best practices and optimization techniques

API Reference

Browse all available algorithms and data structures

Build docs developers (and LLMs) love