# [BZOJ2125]最短路

Description

Input

Output

Sample Input
9 10 2
1 2 1
1 4 1
3 4 1
2 3 1
3 7 1
7 8 2
7 9 2
1 5 3
1 6 4
5 6 1
1 9
5 7

Sample Output
5
6

HINT

（树剖求lca找$x',y'$时细节贼难受……）

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int>pii;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
}
inline int frd(){
int x=0,f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
int x=0,f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0)	putchar('-'),x=-x;
if (x>9)	print(x/10);
putchar(x%10+'0');
}
const int N=1e4;
int V[N+10],cnt,n,m,q;
struct node{
int lca,x,y;
node(){lca=x=y=0;}
node(int _l,int _x,int _y){lca=_l,x=_x,y=_y;}
void insert(int _l,int _x,int _y){lca=_l,x=_x,y=_x;}
};
struct S1{
int pre[(N<<2)+10],now[(N<<1)+10],child[(N<<2)+10],val[(N<<2)+10],tot;
int fa[(N<<1)+10],deep[(N<<1)+10],top[(N<<1)+10],Rem[(N<<1)+10],size[(N<<1)+10],dis[(N<<1)+10];
void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
void dfs(int x){
deep[x]=deep[fa[x]]+1,size[x]=1;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa[x])	continue;
fa[son]=x,dis[son]=dis[x]+val[p];
dfs(son),size[x]+=size[son];
if (size[Rem[x]]<size[son])	Rem[x]=son;
}
}
void build(int x){
if (!x)	return;
top[x]=Rem[fa[x]]==x?top[fa[x]]:x;
build(Rem[x]);
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa[x]||son==Rem[x])	continue;
build(son);
}
}
node LCA(int x,int y){
int lastx=0,lasty=0;
while (top[x]!=top[y]){
if (deep[top[x]]<deep[top[y]])	lasty=top[y],y=fa[top[y]];
else	lastx=top[x],x=fa[top[x]];
}
if (x==y)	return node(x,lastx,lasty);
if (deep[x]<deep[y])	return node(x,lastx,Rem[x]);
else	return node(y,Rem[y],lasty);
//WA了好几次，画了图才发现应该这样写……
}
}RST;//Round Square Tree
struct S2{
int pre[(N<<2)+10],now[N+10],child[(N<<2)+10],val[(N<<2)+10];
int fa[N+10],dfn[N+10],low[N+10],fv[N+10],dis[N+10],stack[N+10],belong[N+10];
bool instack[N+10];
int tot,Time,top,num;
void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
int distant(int x,int y,int pos){
if (dfn[x]<dfn[y])	swap(x,y);
return min(dis[x]-dis[y],V[pos]-(dis[x]-dis[y]));
}
void dfs(int x){
dfn[x]=++Time;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa[x])	continue;
if (!dfn[son]){
fa[son]=x,dis[son]=dis[x]+val[p];
fv[son]=val[p],dfs(son);
}else	if (dfn[son]<dfn[x]){
V[++cnt]=val[p],RST.insert(cnt+n,son,0);
for (int i=x;i!=son;i=fa[i])	V[cnt]+=fv[i];
for (int i=x;i!=son;i=fa[i])	RST.insert(cnt+n,i,distant(i,son,cnt));
}
}
}
void tarjan(int x,int fa){//不论如何枚举顺序都是一样的，那么dfn就算再次dfs也是一样的
dfn[x]=low[x]=++Time;
instack[stack[++top]=x]=1;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa)	continue;
if (!dfn[son])	tarjan(son,x),low[x]=min(low[x],low[son]);
else	if (instack[son])	low[x]=min(low[x],dfn[son]);
}
if (dfn[x]==low[x]){
belong[x]=++num;
instack[x]=0;
while (stack[top]!=x)	belong[stack[top]]=num,instack[stack[top--]]=0;
top--;
}
}
void init(){
Time=0;
memset(dfn,0,sizeof(dfn));
}
}OT;//Original Tree
struct S3{
int x,y,z;
void insert(int _x,int _y,int _z){x=_x,y=_y,z=_z;}
}Line[(N<<1)+10];
int main(){
for (int i=1;i<=m;i++){
OT.insert(x,y,z);
Line[i].insert(x,y,z);
}
OT.dfs(1),OT.init(),OT.tarjan(1,0);
for (int i=1;i<=m;i++)
if (OT.belong[Line[i].x]!=OT.belong[Line[i].y])
RST.insert(Line[i].x,Line[i].y,Line[i].z);
RST.dfs(1),RST.build(1);
for (int i=1;i<=q;i++){