You are given a weighed undirected connected graph, consisting of nn vertices and mmedges.
You should answer qq queries, the ii-th query is to find the shortest distance between vertices uiui and vivi.
Input
The first line contains two integers nn and m (1≤n,m≤105,m−n≤20)m (1≤n,m≤105,m−n≤20) — the number of vertices and edges in the graph.
Next mm lines contain the edges: the ii-th edge is a triple of integers vi,ui,di (1≤ui,vi≤n,1≤di≤109,ui≠vi)vi,ui,di (1≤ui,vi≤n,1≤di≤109,ui≠vi). This triple means that there is an edge between vertices uiui and vivi of weight didi. It is guaranteed that graph contains no self-loops and multiple edges.
The next line contains a single integer q (1≤q≤105)q (1≤q≤105) — the number of queries.
Each of the next qq lines contains two integers uiui and vi (1≤ui,vi≤n)vi (1≤ui,vi≤n) — descriptions of the queries.
Pay attention to the restriction m−n ≤ 20m−n ≤ 20.
Output
Print qq lines.
The ii-th line should contain the answer to the ii-th query — the shortest distance between vertices uiui and vivi.
Examples
Input
3 3
1 2 3
2 3 1
3 1 5
3
1 2
1 3
2 3
Output
3
4
1
Input
8 13
1 2 4
2 3 6
3 4 1
4 5 12
5 6 3
6 7 8
7 8 7
1 4 1
1 8 3
2 6 9
2 7 1
4 6 3
6 8 2
8
1 5
1 7
2 3
2 8
3 7
3 4
6 8
7 8
Output
7
5
6
7
7
1
2
7
代码:
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int n,m,dd[MAXN],head[MAXN],par[MAXN][20],head1[MAXN],tot1,tot;
long long dis[MAXN];
struct edge
{
int u,v,nxt;
long long w;
}edg[MAXN<<1],e[MAXN],edg1[MAXN<<1];
inline void addedg(int u,int v,long long w)
{
edg[tot].v = v;
edg[tot].w = w;
edg[tot].nxt = head[u];
head[u] = tot++;
}
inline void addedg1(int u,int v,long long w)
{
edg1[tot1].v = v;
edg1[tot1].w = w;
edg1[tot1].nxt = head1[u];
head1[u] = tot1++;
}
vector<int> ve;
int pre[MAXN],cnt,st[50];
int find(int x)
{
return x == pre[x]?x:pre[x] = find(pre[x]);
}
inline bool merge(int x,int y)
{
int zx = find(x),zy = find(y);
if(zx == zy)
{
st[cnt++] = x,st[cnt++] = y;
return false;
}
else
{
pre[zx] = zy;
return true;
}
}
void dfs(int k,int fa,int dep,long long w)
{
dd[k] = dep,dis[k] = w;
if(k == 1)
for(int i = 19;i >= 0;--i)
par[k][i] = k;
else
{
par[k][0] = fa;
for(int i = 1;i <= 19;++i)
par[k][i] = par[par[k][i-1]][i-1];
}
for(int i = head[k];i != -1;i = edg[i].nxt)
if(edg[i].v != fa)
dfs(edg[i].v,k,dep+1,w+edg[i].w);
}
inline int jump(int u,int d)
{
for(int i = 19;i >= 0;--i)
if((1<<i)&d)
u = par[u][i];
return u;
}
inline int LCA(int u,int v)
{
if(dd[u] < dd[v])
swap(u,v);
u = jump(u,dd[u]-dd[v]);
if(u == v)
return u;
for(int i = 19;i >= 0;--i)
{
if(par[u][i] != par[v][i])
{
u = par[u][i];
v = par[v][i];
}
}
return par[u][0];
}
struct node
{
int id;
long long w;
node(){}
node(int id,long long w):id(id),w(w){}
friend bool operator<(node n1,node n2)
{
return n2.w < n1.w;
}
}nod;
priority_queue<node> qu;
long long dis1[50][MAXN];
inline void dijkstra(int s,int k)
{
while(!qu.empty())
qu.pop();
dis1[k][s] = 0;
qu.push(node(s,0));
while(!qu.empty())
{
nod = qu.top();
qu.pop();
if(dis1[k][nod.id] != nod.w)
continue;
for(int i = head1[nod.id];i != -1;i = edg1[i].nxt)
{
int v = edg1[i].v;
if(dis1[k][nod.id] + edg1[i].w < dis1[k][v])
{
dis1[k][v] = dis1[k][nod.id] + edg1[i].w;
qu.push(node(v,dis1[k][v]));
}
}
}
}
inline void init()
{
memset(head,-1,4*n+4);
memset(head1,-1,4*n+4);
memset(dis1,0x3f,sizeof(dis1));
tot = cnt = tot1 = 0;
ve.clear();
for(int i = 1;i <= n;++i)
pre[i] = i;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i = 1;i <= m;++i)
{
scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w);
addedg1(e[i].u,e[i].v,e[i].w);
addedg1(e[i].v,e[i].u,e[i].w);
if(merge(e[i].u,e[i].v))
{
addedg(e[i].u,e[i].v,e[i].w);
addedg(e[i].v,e[i].u,e[i].w);
}
}
sort(st,st+cnt);
cnt = unique(st,st+cnt) - st;
for(int i = 0;i < cnt;++i)
dijkstra(st[i],i);
dfs(1,1,1,0);
int q,u,v;
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&u,&v);
long long ans = dis[u] + dis[v] - 2*dis[LCA(u,v)];
for(int i = 0;i < cnt;++i)
ans = min(ans,dis1[i][u] + dis1[i][v]);
printf("%lld\n",ans);
}
}
return 0;
}