# 【BZOJ2125】—最短路（圆方树+树链剖分）

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
#define file freopen("lx.cpp","r",stdin);
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
return (ib==ob)?EOF:*ib++;
}
char ch=gc();
int res=0,f=0;
while(!isdigit(ch))f^=(ch=='-'),ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?-res:res;
}
const int N=40004;
struct Graph{
inline void add(int u,int v,int w){
}
inline void addedge(int u,int v,int w){
}
}G,T;
int n,m,q;
int dfn[N],fa[N],dep[N],bel,plc[N],dis[N],low[N],stk[N],tot,len[N];
inline void buildRec(int u,int v,int w){
int top=dep[v]-dep[u]+1,sum=w,dt=0;
for(int i=v;i!=u;i=fa[i])stk[top--]=i,sum+=dis[i]-dis[fa[i]];
bel++,len[bel]=sum,stk[1]=u;
for(int i=1;i<=dep[v]-dep[u]+1;i++){
int d=min(dt,sum-dt);
plc[stk[i]]=d==dt;
dt+=dis[stk[i+1]]-dis[stk[i]];
}
}
void tarjan(int u){
dfn[u]=low[u]=++tot;
int v=G.to[e];
if(v==fa[u])continue;
if(!dfn[v]){
fa[v]=u,dep[v]=dep[u]+1,dis[v]=dis[u]+G.val[e];
tarjan(v),low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],dfn[v]);
}
int v=G.to[e];
if(v==fa[u])continue;
if(fa[v]!=u&&dfn[u]<dfn[v])buildRec(u,v,G.val[e]);
}
}
namespace SLPF{
int pos[N],idx[N],siz[N],son[N],dis[N],fa[N],top[N],dep[N],tot;
void dfs1(int u){
siz[u]=1;
int v=T.to[e];
if(v==fa[u])continue;
dep[v]=dep[u]+1,fa[v]=u,dis[v]=dis[u]+T.val[e];
dfs1(v),siz[u]+=siz[v];
if(siz[u]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
pos[u]=++tot,idx[tot]=u,top[u]=tp;
if(son[u])dfs2(son[u],tp);
int v=T.to[e];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
inline int Lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}return dep[u]>dep[v]?v:u;
}
inline int jump(int u,int g){
int pre;
while(top[u]!=top[g]){
pre=top[u],u=fa[top[u]];
}
return u==g?pre:idx[pos[g]+1];
}
inline int query(int u,int v){
int lca=Lca(u,v);
if(lca<=n)return dis[u]+dis[v]-2*dis[lca];
int sonu=jump(u,lca),sonv=jump(v,lca);
int du=dis[sonu]-dis[lca],dv=dis[sonv]-dis[lca];
if(plc[sonu])du=len[lca]-du;if(plc[sonv])dv=len[lca]-dv;
if(du<dv)swap(du,dv);
return min(du-dv,len[lca]-du+dv)+dis[u]-dis[sonu]+dis[v]-dis[sonv];
}
}
int main(){
//file;