#pragma once
#include"../graph/graph-utility.hpp"// restore shortest path from S to Gtemplate<typenameT>vector<int>restore_shortest_path(WeightedGraph<T>&g,vector<T>&d,intS,intG){intN=g.size();WeightedGraph<T>rev(g.size());for(inti=0;i<N;i++)for(auto&e:g[i])rev[e.to].emplace_back(e.to,i,e.cost);vector<int>ret;ret.push_back(G);intp=G;Tdist=d[G];vector<int>vis(N,0);vis[G]=1;do{intnxt=-1;Tnval=numeric_limits<T>::max()/2;for(auto&e:rev[p]){if(vis[e.to]||d[e.to]+e.cost!=dist)continue;if(d[e.to]!=-1&&d[e.to]<nval)nval=d[e.to],nxt=e.to;}ret.push_back((vis[nxt]=1,dist=nval,p=nxt));}while(p!=S);reverse(begin(ret),end(ret));returnret;}
#line 2 "shortest-path/restore-shortest-path.hpp"
#line 2 "graph/graph-utility.hpp"
#line 2 "graph/graph-template.hpp"
template<typenameT>structedge{intsrc,to;Tcost;edge(int_to,T_cost):src(-1),to(_to),cost(_cost){}edge(int_src,int_to,T_cost):src(_src),to(_to),cost(_cost){}edge&operator=(constint&x){to=x;return*this;}operatorint()const{returnto;}};template<typenameT>usingEdges=vector<edge<T>>;template<typenameT>usingWeightedGraph=vector<Edges<T>>;usingUnweightedGraph=vector<vector<int>>;// Input of (Unweighted) GraphUnweightedGraphgraph(intN,intM=-1,boolis_directed=false,boolis_1origin=true){UnweightedGraphg(N);if(M==-1)M=N-1;for(int_=0;_<M;_++){intx,y;cin>>x>>y;if(is_1origin)x--,y--;g[x].push_back(y);if(!is_directed)g[y].push_back(x);}returng;}// Input of Weighted Graphtemplate<typenameT>WeightedGraph<T>wgraph(intN,intM=-1,boolis_directed=false,boolis_1origin=true){WeightedGraph<T>g(N);if(M==-1)M=N-1;for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;cin>>c;if(is_1origin)x--,y--;g[x].emplace_back(x,y,c);if(!is_directed)g[y].emplace_back(y,x,c);}returng;}// Input of Edgestemplate<typenameT>Edges<T>esgraph([[maybe_unused]]intN,intM,intis_weighted=true,boolis_1origin=true){Edges<T>es;for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;if(is_weighted)cin>>c;elsec=1;if(is_1origin)x--,y--;es.emplace_back(x,y,c);}returnes;}// Input of Adjacency Matrixtemplate<typenameT>vector<vector<T>>adjgraph(intN,intM,TINF,intis_weighted=true,boolis_directed=false,boolis_1origin=true){vector<vector<T>>d(N,vector<T>(N,INF));for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;if(is_weighted)cin>>c;elsec=1;if(is_1origin)x--,y--;d[x][y]=c;if(!is_directed)d[y][x]=c;}returnd;}/**
* @brief グラフテンプレート
*/#line 4 "graph/graph-utility.hpp"
// 一般のグラフのstからの距離!!!!// unvisited nodes : d = -1vector<int>Depth(constUnweightedGraph&g,intstart=0){intn=g.size();vector<int>ds(n,-1);ds[start]=0;queue<int>q;q.push(start);while(!q.empty()){intc=q.front();q.pop();intdc=ds[c];for(auto&d:g[c]){if(ds[d]==-1){ds[d]=dc+1;q.push(d);}}}returnds;}// Depth of Rooted Weighted Tree// unvisited nodes : d = -1template<typenameT>vector<T>Depth(constWeightedGraph<T>&g,intstart=0){vector<T>d(g.size(),-1);autodfs=[&](autorec,intcur,Tval,intpar=-1)->void{d[cur]=val;for(auto&dst:g[cur]){if(dst==par)continue;rec(rec,dst,val+dst.cost,cur);}};dfs(dfs,start,0);returnd;}// Diameter of Tree// return value : { {u, v}, length }pair<pair<int,int>,int>Diameter(constUnweightedGraph&g){autod=Depth(g,0);intu=max_element(begin(d),end(d))-begin(d);d=Depth(g,u);intv=max_element(begin(d),end(d))-begin(d);returnmake_pair(make_pair(u,v),d[v]);}// Diameter of Weighted Tree// return value : { {u, v}, length }template<typenameT>pair<pair<int,int>,T>Diameter(constWeightedGraph<T>&g){autod=Depth(g,0);intu=max_element(begin(d),end(d))-begin(d);d=Depth(g,u);intv=max_element(begin(d),end(d))-begin(d);returnmake_pair(make_pair(u,v),d[v]);}// nodes on the path u-v ( O(N) )template<typenameG>vector<int>Path(G&g,intu,intv){vector<int>ret;intend=0;autodfs=[&](autorec,intcur,intpar=-1)->void{ret.push_back(cur);if(cur==v){end=1;return;}for(intdst:g[cur]){if(dst==par)continue;rec(rec,dst,cur);if(end)return;}if(end)return;ret.pop_back();};dfs(dfs,u);returnret;}/**
* @brief グラフユーティリティ
*/#line 4 "shortest-path/restore-shortest-path.hpp"
// restore shortest path from S to Gtemplate<typenameT>vector<int>restore_shortest_path(WeightedGraph<T>&g,vector<T>&d,intS,intG){intN=g.size();WeightedGraph<T>rev(g.size());for(inti=0;i<N;i++)for(auto&e:g[i])rev[e.to].emplace_back(e.to,i,e.cost);vector<int>ret;ret.push_back(G);intp=G;Tdist=d[G];vector<int>vis(N,0);vis[G]=1;do{intnxt=-1;Tnval=numeric_limits<T>::max()/2;for(auto&e:rev[p]){if(vis[e.to]||d[e.to]+e.cost!=dist)continue;if(d[e.to]!=-1&&d[e.to]<nval)nval=d[e.to],nxt=e.to;}ret.push_back((vis[nxt]=1,dist=nval,p=nxt));}while(p!=S);reverse(begin(ret),end(ret));returnret;}