Language: C++

#include "bits/stdc++.h"
using namespace std;
using ll = long long int;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pll = pair<ll, ll>;

// Graph.h start--------------------------------------------
#pragma once

#include <vector>

using Weight = long long;

struct Vertex;
using Vertices = std::vector<Vertex *>;
struct Edge;
using Edges = std::vector<const Edge *>;

struct Vertex {
	const int id;
	Edges edges;
	Vertex(int id);
	void add_edge(const Edge *const p_e);
	void add_edge(const Edges &es);
};

struct Edge {
	Vertex *p_src, *p_dst;
	Weight weight;

	Edge(Vertex *p_src, Vertex *p_dst, Weight weight);
	Edge(const Edge &e);
	Edge& operator = (const Edge &de);
};

struct Graph {
	Vertices vertices;
	Edges edges;
	Graph(int nvertices);
	Graph();
	~Graph();
	Graph(Graph&& r)
	{
		vertices = move(r.vertices);
		edges = move(r.edges);
	}
	Graph& operator=(Graph&& r)
	{
		for (auto &p_vertex : vertices) {
			delete p_vertex;
		}
		for (auto &p_edge : edges) {
			delete p_edge;
		}
		vertices = move(r.vertices);
		edges = move(r.edges);
		return *this;
	}
	void add_edge(Edge *p_edge);
	void add_edge(int edge_src, int edge_dst, Weight w);
	void add_edge(int edge_src, int edge_dst);
};

//----------------------------------------------------------

using namespace std;

Vertex::Vertex(int id) : id(id) { }
void Vertex::add_edge(const Edge *const p_e) {
	edges.push_back(p_e);
}
void Vertex::add_edge(const Edges &es) {
	for (const auto &p_e : es) {
		add_edge(p_e);
	}
}

Edge::Edge(Vertex *p_src, Vertex *p_dst, Weight weight) : p_src(p_src), p_dst(p_dst), weight(weight) { }
Edge::Edge(const Edge &e) : Edge(e.p_src, e.p_dst, e.weight) {}
Edge& Edge::operator = (const Edge &e) {
	p_src = e.p_src;
	p_dst = e.p_dst;
	weight = e.weight;
	return *this;
}
bool operator < (const Edge &e1, const Edge &e2) {
	return e1.weight != e2.weight ? e1.weight > e2.weight : // !!INVERSE!!
	e1.p_src != e2.p_src ? e1.p_src->id < e2.p_src->id : e1.p_dst->id < e2.p_dst->id;
}

Graph::Graph(int nvertices) {
	for (int id = 0; id < nvertices; id++) {
		vertices.push_back(new Vertex(id));
	}
}
Graph::Graph() : Graph(0) {}
Graph::~Graph() {
	for (auto &p_vertex : vertices) {
		delete p_vertex;
	}
	for (auto &p_edge : edges) {
		delete p_edge;
	}
}
void Graph::add_edge(Edge *p_edge) {
	vertices[p_edge->p_src->id]->add_edge(p_edge);
	edges.push_back(p_edge);
}
void Graph::add_edge(int edge_src, int edge_dst, Weight w) {
	add_edge(new Edge(vertices[edge_src], vertices[edge_dst], w));
}
void Graph::add_edge(int edge_src, int edge_dst) {
	add_edge(edge_src, edge_dst, 0);
}

// Graph.h end----------------------------------------------
// ShortPath.h start----------------------------------------
#pragma once

#include "Graph.h"

std::vector<Weight> dijkstra(const Graph &g, const int id_start, const Weight INF);
std::vector<Weight> bellman_ford(const Graph &g, const int id_start, const Weight INF);
std::vector<vector<Weight>> warshall_floyd(const Graph &g, const Weight INF);

//----------------------------------------------------------
#include <queue>


vector<Weight> dijkstra(const Graph &g, const int id_start, const Weight INF) { // INFに気を付けよ
	using Pwi = pair<Weight, int>;

	const size_t n = g.vertices.size();
	vector<Weight> d(n, INF);
	vector<bool> is_used(n, false);
	priority_queue<Pwi, vector<Pwi>, greater<Pwi>> que;

	d[id_start] = 0;
	for (que.push(Pwi(0, id_start)); !que.empty(); ) {
		Pwi p = que.top(); que.pop();
		const int tmpid = p.second; // p.first >= d[tmpid]
		if (is_used[tmpid]) continue;
		is_used[tmpid] = true;
		//assert(p.first == d[tmpid]);
		for (const auto &p_nxte : g.vertices[tmpid]->edges) {
			const int nxtid = p_nxte->p_dst->id;
			Weight nxtd = d[tmpid] + p_nxte->weight;
			if (d[nxtid] > nxtd) {
				d[nxtid] = nxtd;
				que.push(Pwi(nxtd, nxtid));
			}
		}
	}
	return d;
}

vector<Weight> bellman_ford(const Graph &g, const int id_start, const Weight INF) {
	// INFに気を付けよ d_max < INF
	// 負の閉路からアクセスできる頂点にはd = -INF
	const size_t n = g.vertices.size();
	vector<Weight> d(n, INF);
	d[id_start] = 0;
	bool is_negative_cycle = false;
	for (size_t i = 1; i <= n; i++)
	{
		for (const auto &p_tmpe : g.edges) {
			const int id_src = p_tmpe->p_src->id;
			const int id_dst = p_tmpe->p_dst->id;
			if (d[id_src] != INF && d[id_dst] > d[id_src] + p_tmpe->weight) {
				d[id_dst] = d[id_src] + p_tmpe->weight;
				if (i == n) {
					d[id_dst] = -INF;
					is_negative_cycle = true;
				}
			}
		}
	}
	if (is_negative_cycle) {
		for (size_t i = 1; i < n; i++)
		{
			for (const auto &p_tmpe : g.edges) {
				const int id_src = p_tmpe->p_src->id;
				const int id_dst = p_tmpe->p_dst->id;
				if (d[id_src] == -INF && d[id_dst] != -INF) {
					d[id_dst] = -INF;
				}
			}
		}
	}
	return d;
}

vector<vector<Weight>> warshall_floyd(const Graph &g, const Weight INF) {
	const size_t n = g.vertices.size();
	vector<vector<Weight>> d(n, vector<Weight>(n, INF));
	for (size_t id = 0; id < n; id++)
	{
		d[id][id] = 0;
	}

	for (const auto &p_tmpe : g.edges) {
		d[p_tmpe->p_src->id][p_tmpe->p_dst->id] = p_tmpe->weight;
	}
	for (size_t id_new = 0; id_new < n; id_new++)
	{
		for (size_t id_src = 0; id_src < n; id_src++)
		{
			for (size_t id_dst = 0; id_dst < n; id_dst++)
			{
				if (d[id_src][id_dst] > d[id_src][id_new] + d[id_new][id_dst]) {
					d[id_src][id_dst] = d[id_src][id_new] + d[id_new][id_dst];
				}
			}
		}
	}
	return d;
}

// ShortPath.h end------------------------------------------
int N, M;
vector<int> u, v;
int S, T;

int main() {
	cin >> N >> M;
	u.assign(M, 0);
	v.assign(M, 0);
	for (int j = 0; j < M; j++)
		cin >> u[j] >> v[j];
	cin >> S >> T;

	Graph g(N + 1);
	for (int j = 0; j < M; j++)
	{
		g.add_edge(u[j], v[j]);
	}
	vector<int> states(N + 1, -1); //-1...not reached, 0or1or2 ...state, 3...all states
	Graph g2(N + 1);
	Graph g3(N + 1);
	vector<bool> is_2(N + 1, false);
	for (int tid = 1; tid <= N; tid++)
	{
		for (const auto e : g.vertices[tid]->edges) {
			int n1id = e->p_dst->id;
			if (is_2[n1id]) {
				for (const auto e2 : g2.vertices[n1id]->edges)
					g3.add_edge(tid, e2->p_dst->id, 1);
				continue;
			}
			is_2[n1id] = true;
			for (const auto e2 : g.vertices[n1id]->edges) {
				int n2id = e2->p_dst->id;
				for (const auto e3 : g.vertices[n2id]->edges) {
					int n3id = e3->p_dst->id;
					g2.add_edge(n1id, n3id);
					g3.add_edge(tid, n3id, 1);
				}
			}
		}
	}

	const int INF = 1000000000;
	vector<Weight> saitan = dijkstra(g3, S, INF);
	if (saitan[T] == INF)
		cout << -1 << endl;
	else {
		cout << saitan[T] << endl;
	}
	return 0;
}


Compiler output:
a.cc:9:9: warning: #pragma once in main file
    9 | #pragma once
      |         ^~~~
a.cc:119:9: warning: #pragma once in main file
  119 | #pragma once
      |         ^~~~
a.cc:121:10: fatal error: Graph.h: No such file or directory
  121 | #include "Graph.h"
      |          ^~~~~~~~~
compilation terminated.