1. Abridged Problem Statement  
Given a directed graph with N vertices and M edges, each edge colored 1, 2, or 3, find the minimum number of edges in a walk from vertex 1 to vertex N such that no two consecutive edges have the same color. If no such path exists, print –1.

2. Detailed Editorial  

Problem restatement  
- Vertices are numbered from 1 to N.  
- Edges are directed and each carries one of three possible colors (1, 2, 3).  
- You must travel from vertex 1 to vertex N, minimizing the total number of edges used, under the constraint that you cannot take two edges of the same color in a row.

Key observations  
- Every time you traverse an edge, its color matters relative to the previous edge’s color.  
- A standard shortest-path algorithm on vertices only is not enough, because the “state” must also remember the color of the edge just taken.  

State definition  
Define state (u, c) = “you are at vertex u, and the last edge used to reach u had color c.” We index colors from 0 to 2 internally instead of 1–3.

Transitions  
From state (u, last_color), you may follow any outgoing edge e = (u → v) of color col ≠ last_color, moving to state (v, col) with an added cost of 1.

Initialization  
- We start at vertex 1 with no previous edge, so we can model this by allowing initial “last_color” to be any of 0,1,2, all at distance 0.  
- Then perform a breadth-first search (BFS) over the augmented state space of size N×3 = up to 600.  

Distance array  
dist[u][c] = minimum number of edges to reach vertex u with last edge color = c.

Answer  
Once BFS completes, look at dist[N][0], dist[N][1], dist[N][2], and take the minimum. If still infinite, answer is –1.

Time & memory  
- States: O(3N) = O(N).  
- Transitions: each edge is considered at most 3 times (once for each possible last_color ≠ edge_color). So O(3M).  
- N ≤ 200, M ≤ N² = 40 000 is easily handled in 0.25 s.

3. Provided C++ Solution with Detailed Comments  

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

// Overload << for pairs (for easy debugging, not used in final solution)
template<typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &x) {
    return out << x.first << ' ' << x.second;
}

// Overload >> for pairs (not strictly needed here)
template<typename T1, typename T2>
istream &operator>>(istream &in, pair<T1, T2> &x) {
    return in >> x.first >> x.second;
}

// Overload >> for vectors (reads elements in sequence)
template<typename T>
istream &operator>>(istream &in, vector<T> &a) {
    for(auto &x: a) {
        in >> x;
    }
    return in;
};

// Overload << for vectors (prints elements space-separated)
template<typename T>
ostream &operator<<(ostream &out, const vector<T> &a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

const int inf = (int)1e9;    // A large number to represent infinity

int n, m;    // Number of vertices and edges
// Adjacency list: for each u, store (v, color) pairs
vector<vector<pair<int, int>>> adj;

// Read input
void read() {
    cin >> n >> m;
    adj.assign(n, {});             // Resize adjacency list to n
    for(int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        // Convert to 0-based indexing
        u--; v--; w--;
        // Add directed edge u -> v with color w
        adj[u].push_back({v, w});
    }
}

// Solve one test case
void solve() {
    // dist[u][c] = shortest path length to u with last edge color c
    vector<vector<int>> dist(n, vector<int>(3, inf));
    // Starting at vertex 0 (originally vertex 1), with any 'previous color'
    dist[0] = {0, 0, 0};

    // BFS queue holds states (vertex, last_color)
    queue<pair<int, int>> q;
    // Push the three possible start states
    q.push({0, 0});
    q.push({0, 1});
    q.push({0, 2});

    // Standard 0-1 BFS, but here all edges cost 1, so it's just plain BFS
    while(!q.empty()) {
        auto [u, last_color] = q.front();
        q.pop();
        // Explore all outgoing edges
        for(auto [v, edge_color] : adj[u]) {
            // Only proceed if colors differ
            if(edge_color != last_color 
               && dist[v][edge_color] > dist[u][last_color] + 1) {
                // Relax distance
                dist[v][edge_color] = dist[u][last_color] + 1;
                q.push({v, edge_color});
            }
        }
    }

    // Answer is the best among the three possible last colors at vertex n-1
    int ans = min({dist[n - 1][0], dist[n - 1][1], dist[n - 1][2]});
    if(ans == inf) {
        cout << -1 << '\n';
    } else {
        cout << ans << '\n';
    }
}

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

    // single test case
    read();
    solve();
    return 0;
}
```

4. Python Solution with Detailed Comments  

```python
from collections import deque
import sys

def main():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    m = int(next(it))
    
    # Build adjacency list: adj[u] = list of (v, color)
    # We'll store colors as 0,1,2 internally
    adj = [[] for _ in range(n)]
    for _ in range(m):
        u = int(next(it)) - 1
        v = int(next(it)) - 1
        c = int(next(it)) - 1
        adj[u].append((v, c))
    
    INF = 10**9
    # dist[u][c] = shortest #edges to reach u with last edge color c
    dist = [[INF]*3 for _ in range(n)]
    # Starting at vertex 0 with any 'last color'
    for c in range(3):
        dist[0][c] = 0
    
    # BFS queue of (vertex, last_color)
    q = deque()
    for c in range(3):
        q.append((0, c))
    
    while q:
        u, last_color = q.popleft()
        d = dist[u][last_color]
        # Traverse all outgoing edges
        for v, c in adj[u]:
            if c != last_color and dist[v][c] > d + 1:
                dist[v][c] = d + 1
                q.append((v, c))
    
    # Answer is the minimum over last_color at vertex n-1
    ans = min(dist[n-1])
    print(-1 if ans >= INF else ans)

if __name__ == "__main__":
    main()
```

5. Compressed Editorial  

- Model each state as (vertex, last_edge_color) to enforce the “no two adjacent edges share the same color” constraint.  
- Initialize all three “last_color” variants at the source with distance 0 and run a BFS on this expanded state space.  
- Each transition uses exactly one more edge (cost=1) and is allowed only if the new edge’s color differs from last_color.  
- Final answer = min distance for (N, any color), or –1 if unreachable.