#include #include using namespace std; using ll = long long; #define rep(i, s, t) for (ll i = s; i < (ll)(t); i++) #define all(x) begin(x), end(x) template bool chmin(T& x, T y) { return x > y ? (x = y, true) : false; } template bool chmax(T& x, T y) { return x < y ? (x = y, true) : false; } // https://ei1333.github.io/library/graph/connected-components/bi-connected-components.hpp.html #line 2 "graph/graph-template.hpp" template struct Edge { int from, to; T cost; int idx; Edge() = default; Edge(int from, int to, T cost = 1, int idx = -1) : from(from), to(to), cost(cost), idx(idx) { } operator int() const { return to; } }; template struct Graph { vector>> g; int es; Graph() = default; explicit Graph(int n) : g(n), es(0) { } size_t size() const { return g.size(); } void add_directed_edge(int from, int to, T cost = 1) { g[from].emplace_back(from, to, cost, es++); } void add_edge(int from, int to, T cost = 1) { g[from].emplace_back(from, to, cost, es); g[to].emplace_back(to, from, cost, es++); } void read(int M, int padding = -1, bool weighted = false, bool directed = false) { for (int i = 0; i < M; i++) { int a, b; cin >> a >> b; a += padding; b += padding; T c = T(1); if (weighted) cin >> c; if (directed) add_directed_edge(a, b, c); else add_edge(a, b, c); } } inline vector>& operator[](const int& k) { return g[k]; } inline const vector>& operator[](const int& k) const { return g[k]; } }; template using Edges = vector>; #line 2 "graph/others/low-link.hpp" #line 4 "graph/others/low-link.hpp" /** * @brief Low Link(橋/関節点) * @see http://kagamiz.hatenablog.com/entry/2013/10/05/005213 * */ template struct LowLink : Graph { public: using Graph::Graph; vector ord, low, articulation; vector> bridge; using Graph::g; virtual void build() { used.assign(g.size(), 0); ord.assign(g.size(), 0); low.assign(g.size(), 0); int k = 0; for (int i = 0; i < (int)g.size(); i++) { if (!used[i]) k = dfs(i, k, -1); } } explicit LowLink(const Graph& g) : Graph(g) { } private: vector used; int dfs(int idx, int k, int par) { used[idx] = true; ord[idx] = k++; low[idx] = ord[idx]; bool is_articulation = false, beet = false; int cnt = 0; for (auto& to : g[idx]) { if (to == par && !exchange(beet, true)) { continue; } if (!used[to]) { ++cnt; k = dfs(to, k, idx); low[idx] = min(low[idx], low[to]); is_articulation |= par >= 0 && low[to] >= ord[idx]; if (ord[idx] < low[to]) bridge.emplace_back(to); } else { low[idx] = min(low[idx], ord[to]); } } is_articulation |= par == -1 && cnt > 1; if (is_articulation) articulation.push_back(idx); return k; } }; #line 3 "graph/connected-components/bi-connected-components.hpp" template struct BiConnectedComponents : LowLink { public: using LowLink::LowLink; using LowLink::g; using LowLink::ord; using LowLink::low; vector>> bc; void build() override { LowLink::build(); used.assign(g.size(), 0); for (int i = 0; i < (int)used.size(); i++) { if (!used[i]) dfs(i, -1); } } explicit BiConnectedComponents(const Graph& g) : Graph(g) { } private: vector used; vector> tmp; void dfs(int idx, int par) { used[idx] = true; bool beet = false; for (auto& to : g[idx]) { if (to == par && !exchange(beet, true)) continue; if (!used[to] || ord[to] < ord[idx]) { tmp.emplace_back(to); } if (!used[to]) { dfs(to, idx); if (low[to] >= ord[idx]) { bc.emplace_back(); for (;;) { auto e = tmp.back(); bc.back().emplace_back(e); tmp.pop_back(); if (e.idx == to.idx) break; } } } } } }; void solve() { int n, m, s, g; cin >> n >> m >> s >> g; s--, g--; vector> edge(m); for (auto& [a, b] : edge) cin >> a >> b, a--, b--; BiConnectedComponents<> bb(n); for (auto [a, b] : edge) bb.add_edge(a, b); bb.build(); vector>> gg(n); for (auto ve : bb.bc) { if (ve.size() == 1) { auto e = ve[0]; gg[e.from].push_back({e.to, 0}); gg[e.to].push_back({e.from, 0}); continue; } for (auto e : ve) { gg[e.from].push_back({e.to, 1}); gg[e.to].push_back({e.from, 1}); } } vector dist(n, 1e18); using arr = array; priority_queue, greater> pq; pq.push({0, s}); dist[s] = 0; while (!pq.empty()) { auto [d, nw] = pq.top(); pq.pop(); if (dist[nw] < d) continue; for (auto [nx, ad] : gg[nw]) { if (dist[nx] > dist[nw] + ad) { dist[nx] = dist[nw] + ad; pq.push({dist[nx], nx}); } } } if (dist[g] == 1e18) cout << "-1\n"; else cout << dist[g] << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout << fixed << setprecision(15); int t = 1; // cin >> t; while (t--) solve(); }