<p>You are given an array <code>routes</code> representing bus routes where <code>routes[i]</code> is a bus route that the <code>i<sup>th</sup></code> bus repeats forever.</p>

<ul>
	<li>For example, if <code>routes[0] = [1, 5, 7]</code>, this means that the <code>0<sup>th</sup></code> bus travels in the sequence <code>1 -&gt; 5 -&gt; 7 -&gt; 1 -&gt; 5 -&gt; 7 -&gt; 1 -&gt; ...</code> forever.</li>
</ul>

<p>You will start at the bus stop <code>source</code> (You are not on any bus initially), and you want to go to the bus stop <code>target</code>. You can travel between bus stops by buses only.</p>

<p>Return <em>the least number of buses you must take to travel from </em><code>source</code><em> to </em><code>target</code>. Return <code>-1</code> if it is not possible.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> routes = [[1,2,7],[3,6,7]], source = 1, target = 6
<strong>Output:</strong> 2
<strong>Explanation:</strong> The best strategy is take the first bus to the bus stop 7, then take the second bus to the bus stop 6.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12
<strong>Output:</strong> -1
</pre>

<p>&nbsp;</p>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= routes.length &lt;= 500</code>.</li>
	<li><code>1 &lt;= routes[i].length &lt;= 10<sup>5</sup></code></li>
	<li>All the values of <code>routes[i]</code> are <strong>unique</strong>.</li>
	<li><code>sum(routes[i].length) &lt;= 10<sup>5</sup></code></li>
	<li><code>0 &lt;= routes[i][j] &lt; 10<sup>6</sup></code></li>
	<li><code>0 &lt;= source, target &lt; 10<sup>6</sup></code></li>
</ul>

const int MAXSTATION = 1e6;
#include <deque>


struct Graph {
    map<pair<int,int>, vector<tuple<int,int,int>>> adj;
    map<pair<int,int>, int> dis;
    deque<pair<int,int>> q;

    void bfs(vector<pair<int, int>> sources) {
        for(const auto p: sources) {
            dis[p] = 1;
            q.push_back(p);
        }
        
        while(!q.empty()) {
            pair<int, int> u = q.front();
            q.pop_front();
            for(auto [bv, vnode, w] : adj[u]) {
                pair<int, int> v = {bv, vnode};
                if (dis.find(v) == dis.end() || dis[v] > dis[u] + w) {
                    dis[v] = dis[u] + w;
                    if (w == 1) {
                        q.push_back(v);
                    } else {
                        q.push_front(v);
                    }
                }
            }
        }
    }

    int get_dist(int node) {
        int res = INT_MAX;
        for(const auto pp : dis) {
            int v = pp.first.second;
            int d = pp.second;
            if (v == node) {
                res = min(res, d);
            }
        }
        return res == INT_MAX ? -1 : res;
    }
    
    void addEdge(pair<int,int> u, pair<int,int> v, int w) {
        adj[u].emplace_back(v.first, v.second, w);
        adj[v].emplace_back(u.first, u.second, w);
    }
};


class Solution {
    int nBus, src, target;
    vector<vector<int>> routes;

public:
    int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
        if (source == target) return 0;
        nBus = routes.size();
        src = source;
        this->target = target;
        map<int, vector<int>> busOnStation;

        Graph g;
        for(int bus = 0; bus < nBus; ++bus) {
            int m = routes[bus].size();
            
            for (int station : routes[bus]) {
                busOnStation[station].push_back(bus);
            }
            
            if (m == 1) continue;
            for(int i = 1; i < m; ++i) {
                g.addEdge(
                    make_pair(bus, routes[bus][i - 1]), 
                    make_pair(bus, routes[bus][i]),
                    0
                );
            }
            g.addEdge(
                make_pair(bus, routes[bus].back()),
                make_pair(bus, routes[bus][0]),
                0
            );
        }

        for (const auto p : busOnStation) {
            int station = p.first;
            const vector<int> &ve = p.second;
            if (ve.size() < 2) continue;
            for(int i = 1; i < ve.size(); ++i) {
                g.addEdge(
                    make_pair(ve[i - 1], station),
                    make_pair(ve[i], station),
                    1
                );
            }

            g.addEdge(
                make_pair(ve.back(), station),
                make_pair(ve.front(), station),
                1
            );
        }

        vector<pair<int,int>> sourceList;
        for(int bus : busOnStation[source]) {
            sourceList.emplace_back(bus, source);
        }

        g.bfs(sourceList);

        
        return g.get_dist(target);

    }
};
213486