#define PROBLEM "https://yukicoder.me/problems/no/1069" #define ERROR 0.0001 #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 ShortestPathProblemUndirected { using Weight = double; struct Edge { int u, v, uv, id; Weight w; }; int n; Weight inf; Weight zero; std::vector edges; std::vector> inc; int s; int t; ShortestPathProblemUndirected(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 u, int v, Weight w){ int e = edges.size(); edges.push_back({ u, v, u ^ v, e, w }); inc[u].push_back(e); inc[v].push_back(e); return e; } struct ShortestPathTree { std::vector parent; std::vector dist; std::vector root; void resize(int n, Weight inf){ parent.resize(n, -1); dist.resize(n, inf); root.resize(n, -1); } }; void updateTree(const std::vector& edgeMask, ShortestPathTree& tree){ ShortestPathTree t; std::swap(t, tree); using Node = std::pair; std::priority_queue, std::greater> que; auto check = [&](int v, int p, int r, Weight d) -> void { if(!(d < t.dist[v])) return; t.dist[v] = d; t.parent[v] = p; t.root[v] = r; que.push({ d, v }); }; for(int v=0; v getPath(const ShortestPathTree& t, int start){ std::vector path; for(int v=start; t.root[v]!=v; v^=edges[path.back()].uv){ if(t.parent[v] < 0) return {}; path.push_back(t.parent[v]); } std::reverse(path.begin(), path.end()); return path; } ShortestPathTree solve(const std::vector& edgeMask){ ShortestPathTree tree; tree.resize(n, inf); tree.root[s] = s; tree.dist[s] = zero; updateTree(edgeMask, tree); return tree; } struct Instance { ShortestPathProblemUndirected* data; std::vector edgeMask; Weight wt; std::vector path; std::vector> cand; int lim; struct SplitResult { std::vector path; std::vector newInstances; }; Instance(ShortestPathProblemUndirected* _data, std::vector _edgeMask) : data(_data), edgeMask(_edgeMask) {} bool solve(){ auto tree = data->solve(edgeMask); path = data->getPath(tree, data->t); if(path.empty()) return false; lim = path.size(); return true; } bool solve2nd(){ ShortestPathTree treeS, treeT; treeS.resize(data->n, data->inf); treeT.resize(data->n, data->inf); int pathLen = path.size(); std::vector pathVtx(pathLen + 1); pathVtx[0] = data->s; for(int i=0; iedges[path[i]].uv; for(int h : {data->s, data->t}){ treeS.dist[h] = data->zero; treeS.root[h] = h; for(int i=0; iedges[path[i]]; treeS.root[pathVtx[i+1]] = pathVtx[i+1]; treeS.dist[pathVtx[i+1]] = treeS.dist[pathVtx[i]] + e.w; } data->updateTree(edgeMask, treeS); std::swap(treeS, treeT); std::reverse(path.begin(), path.end()); std::reverse(pathVtx.begin(), pathVtx.end()); } std::vector mainPath(data->edges.size(), -1); for(int i=0; i mainPathVtx(data->n, -1); for(int i=0; i<=pathLen; i++) mainPathVtx[pathVtx[i]] = i; std::vector nextWeight(pathLen, data->inf); for(int i=0; iedges.size()); i++) if(edgeMask[i] && mainPath[i] == -1){ auto e = data->edges[i]; for(int t=0; t<2; t++){ std::swap(e.u, e.v); if(treeS.root[e.u] < 0 || treeT.root[e.v] < 0) continue; if(mainPathVtx[treeS.root[e.u]] >= mainPathVtx[treeT.root[e.v]]) continue; Weight& dest = nextWeight[mainPathVtx[treeS.root[e.u]]]; dest = std::min(dest, e.w + treeS.dist[e.u] + treeT.dist[e.v]); } } Weight minWeight = data->inf; for(int i=0; is; for(int i=0; iinc[p]) nextEdgeMask[e] = false; p ^= src.data->edges[src.path[i]].uv; } for(int i=0; is; for(int i=0; i<=rank; i++){ for(int e : src.data->inc[p]) nextEdgeMask[e] = false; p ^= src.data->edges[src.path[i]].uv; } for(int i=0; i<=rank; i++) nextEdgeMask[src.path[i]] = true; nextEdgeMask[src.path[rank]] = false; Instance buf(src.data, std::move(nextEdgeMask)); buf.path = src.path; buf.lim = src.lim; if(buf.solve2nd()) res.newInstances.push_back(std::move(buf)); } if(src.cand.size()){ src.wt = src.cand.back().second; src.lim = rank; res.newInstances.push_back(std::move(src)); } 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)); if(!inst.solve()) return std::nullopt; auto res = inst.path; if(inst.solve2nd()) que.push(std::move(inst)); return res; } if(que.empty()) return std::nullopt; auto h = Instance::split(que.top()); que.pop(); for(auto& nx : h.newInstances) que.push(std::move(nx)); return h.path; } }; #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]; ShortestPathProblemUndirected 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])) + 1.0e-8); } for(int k=0; ksync_with_stdio(0); testcase(); return 0; }