#include #include #include #include using namespace std; using ll = long long; const ll INF = 1ll << 60; #define REP(i,n) for(ll i=0; i using V = vector; template void chmax(A& l, const B& r){ if(l < r) l = r; } template void chmin(A& l, const B& r){ if(r < l) l = r; } #include #include #include #include struct ShortestPathProblemDirected { //using Weight = long long; using Weight = double; struct Edge { int from, to, id; Weight w; }; int n; Weight inf; Weight zero; std::vector edges; std::vector> inc; int s; int t; ShortestPathProblemDirected(int _n, Weight _inf, Weight _zero, int _s, int _t) : n(_n), inf(_inf), zero(_zero), edges(), inc(_n), s(_s), t(_t) {} int addEdge(int from, int to, Weight w){ int e = edges.size(); edges.push_back({ from, to, e, w }); inc[from].push_back(e); return e; } std::vector solve(const std::vector& edgeMask){ if(s == t) return {}; std::vector dist(n, inf); std::vector parent(n, -1); using Node = std::pair; std::priority_queue, std::greater> que; auto check = [&](int v, int p, Weight d) -> void { if(!(d < dist[v])) return; dist[v] = d; parent[v] = p; que.push({ d, v }); }; check(s, -1, zero); while(que.size()){ auto [d, v] = que.top(); que.pop(); if(dist[v] < d) continue; for(int e : inc[v]) if(edgeMask[e]){ check(edges[e].to, e, d + edges[e].w); } } if(parent[t] == -1) return {}; std::vector path; for(int v=t; v!=s; v=edges[path.back()].from){ path.push_back(parent[v]); } std::reverse(path.begin(), path.end()); return path; } struct Instance { ShortestPathProblemDirected* data; std::vector edgeMask; int rank; Weight wt; std::vector path; Instance(ShortestPathProblemDirected* _data, std::vector _edgeMask, int _rank) : data(_data), edgeMask(_edgeMask), rank(_rank) {} bool solve(){ path = data->solve(edgeMask); if(path.empty()) return false; wt = data->zero; for(int e : path) wt += data->edges[e].w; return true; } std::vector split() const { std::vector res; std::vector nextEdgeMask = edgeMask; int v = 0; for(int s=rank; s<(int)path.size(); s++){ nextEdgeMask[path[s]] = false; Instance inst(data, nextEdgeMask, s); if(inst.solve()) res.push_back(std::move(inst)); for(int e : data->inc[data->edges[path[s]].from]) nextEdgeMask[e] = false; nextEdgeMask[path[s]] = true; } return res; } }; struct CmpWt { bool operator()(const Instance& l, const Instance& r){ return r.wt < l.wt; } }; std::priority_queue, CmpWt> que; bool KthStarted = false; std::optional getNextSmallest(){ if(!KthStarted){ KthStarted = true; Instance inst(this, std::vector(edges.size(), true), 0); if(inst.solve()) que.push(std::move(inst)); } else { if(que.empty()) return std::nullopt; auto h = que.top().split(); que.pop(); for(auto& nx : h) que.push(std::move(nx)); } if(que.empty()) return std::nullopt; return que.top().wt; } }; #include void testcase(){ std::cout.precision(15); std::cout << std::fixed; int N, M, K; cin >> N >> M >> K; int X, Y; cin >> X >> Y; X--; Y--; std::vector posX(N), posY(N); for(int i=0; i> posX[i] >> posY[i]; ShortestPathProblemDirected task(N, 1.0e100, 0, X, Y); for(int i=0; i> u >> v; u--; v--; task.addEdge(u, v, hypot(double(posX[u] - posX[v]), double(posY[u] - posY[v]))); task.addEdge(v, u, hypot(double(posX[u] - posX[v]), double(posY[u] - posY[v]))); } for(int k=0; ksync_with_stdio(0); testcase(); return 0; }