You are given a weighed undirected connected graph, consisting of nn vertices and mm edges.

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 n and m (1≤n,m≤105,m−n≤20) — the number of vertices and edges in the graph.

Next m lines contain the edges: the i-th edge is a triple of integers vi,ui,di (1≤ui,vi≤n,1≤di≤109,ui≠vi). This triple means that there is an edge between vertices ui and vi of weight di. It is guaranteed that graph contains no self-loops and multiple edges.

The next line contains a single integer 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 ≤ 20

Output

Print q lines.

The i-th line should contain the answer to the i-th query — the shortest distance between vertices ui and vi.

解题思路:

题目非常良心地强调了m-n<=20

建一颗dfs树,对于未加入树的边两端跑Dij

询问只要枚举未入树边更新即可。

代码:

 #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
struct pnt{
int hd;
int dp;
int no;
int fa[];
lnt dis;
lnt tds;
bool vis;
bool cop;
bool friend operator < (pnt x,pnt y)
{
return x.dis>y.dis;
}
}p[];
struct ent{
int twd;
int lst;
lnt vls;
}e[];
std::priority_queue<pnt>Q;
int n,m;
int q;
int cnt;
int sct;
lnt dist[][];
int sta[];
void ade(int f,int t,lnt v)
{
cnt++;
e[cnt].twd=t;
e[cnt].vls=v;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void Dij(int x)
{
if(p[x].cop)
return ;
p[x].cop=true;
sta[++sct]=x;
for(int i=;i<=n;i++)
{
p[i].dis=0x3f3f3f3f3f3f3f3fll;
p[i].no=i;
p[i].vis=false;
}
p[x].dis=;
while(!Q.empty())
Q.pop();
Q.push(p[x]);
while(!Q.empty())
{
x=Q.top().no;
Q.pop();
if(p[x].vis)
continue;
p[x].vis=true;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].dis>p[x].dis+e[i].vls)
{
p[to].dis=p[x].dis+e[i].vls;
Q.push(p[to]);
}
}
}
for(int i=;i<=n;i++)
dist[sct][i]=p[i].dis;
return ;
}
void dfs(int x,int f)
{
p[x].fa[]=f;
p[x].dp=p[f].dp+;
for(int i=;i<=;i++)
p[x].fa[i]=p[p[x].fa[i-]].fa[i-];
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
if(p[to].tds)
{
Dij(x);
Dij(to);
}else{
p[to].tds=p[x].tds+e[i].vls;
dfs(to,x);
}
}
}
int Lca(int x,int y)
{
if(p[x].dp<p[y].dp)
std::swap(x,y);
for(int i=;i>=;i--)
if(p[p[x].fa[i]].dp>=p[y].dp)
x=p[x].fa[i];
if(x==y)
return x;
for(int i=;i>=;i--)
if(p[x].fa[i]!=p[y].fa[i])
{
x=p[x].fa[i];
y=p[y].fa[i];
}
return p[x].fa[];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ade(a,b,c);
ade(b,a,c);
}
p[].tds=;
dfs(,);
scanf("%d",&q);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int f=Lca(x,y);
lnt ans=p[x].tds+p[y].tds-*p[f].tds;
for(int i=;i<=sct;i++)
ans=std::min(ans,dist[i][x]+dist[i][y]);
printf("%I64d\n",ans);
}
return ;
}

cf1051F. The Shortest Statement(最短路/dfs树)的更多相关文章

  1. cf1051F. The Shortest Statement(最短路)

    题意 题目链接 题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$ $n, m, q \leqslant 10^5$ Sol 非常好的一道题. 首先建出一个dfs树. ...

  2. 【题解】Luogu CF1051F The Shortest Statement

    原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开 ...

  3. [CF1051F]The Shortest Statement (LCA+最短路)(给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路)

    题目:给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路 n≤100000,m≤100000,m-n≤20. 首先看到m-n≤20这条限制,我们可以想到是围绕这个20来做这道题. 即如果我们 ...

  4. [Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)

    题目链接: https://codeforces.com/contest/1051/problem/F 题目大意: 给出一张$n$个点,$m$条边的带权无向图,多次询问,每次给出$u,v$,要求输出$ ...

  5. [CF1051F]The Shortest Statement

    题目大意:给定一张$n$个点$m$条有权边的无向联通图,$q$次询问两点间的最短路 $n\le100000$,$m\le100000$,$1\le100000$,$m$-$n\le20$. 首先看到$ ...

  6. CF1051F The Shortest Statement 题解

    题目 You are given a weighed undirected connected graph, consisting of n vertices and m edges. You sho ...

  7. Codeforces.1051F.The Shortest Statement(最短路Dijkstra)

    题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...

  8. CF1051F The Shortest Statement Dijkstra + 性质分析

    动态询问连通图任意两点间最短路,单次询问. 显然,肯定有一些巧妙地性质(不然你就发明了新的最短路算法了233)有一点很奇怪:边数最多只比点数多 $20$ 个,那么就可以将这个图看作是一个生成树,上面连 ...

  9. Educational Codeforces Round 51 (Rated for Div. 2) F - The Shortest Statement 倍增LCA + 最短路

    F - The Shortest Statement emmm, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...

随机推荐

  1. java枚举在android项目应用

    今天修复一个公司非常早曾经的android应用功能,里面的代码逻辑已经全然错乱,然后发现返回的数据全然不正确了.然后修复了整整两天.然后我又一次整理了一遍,重构就算不上了. 然后就用上了枚举. 什么是 ...

  2. vue7 下拉列表

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. CentOS中实现与Ubuntu下apt-get install build-essential功能类似的命令

    CentOS中实现与Ubuntu下apt-get install build-essential功能类似的命令 在Ubuntu中安装完系统后,可以直接使用apt-get install build-e ...

  4. 使用PyV8模块破解网站加密cookie

    PyV8是Chromium中内嵌的javascript引擎,号称跑的最快.PyV8是用Python在V8的外部API包装了一个python壳,这样便可以使python可以直接与javascript操作 ...

  5. DEDE 修改后台图集上传单个图片的大小限制

    默认情况下,DEDE图集中单个图片大小限制在2M以内,而有时我们需要上传一个2M以上的文件,这是只要修改几个文件就可以实现了. 一.需要修改php.ini这个文件,我们必须保证PHP的配置中允许上传一 ...

  6. Java main方法中的String[] args

    -- Java 命令行参数 -- 关于其中的args以及public static / static public Java 命令行参数 前面已经看到多个使用Java数组的示例,每一个Java应用程序 ...

  7. BZOJ2137: submultiple(生成函数,二项式定理)

    Description 设函数g(N)表示N的约数个数.现在给出一个数M,求出所有M的约数x的g(x)的K次方和. Input 第一行输入N,K.N表示M由前N小的素数组成.接下来N行,第i+1行有一 ...

  8. 【Henu ACM Round#15 C】 A and B and Team Training

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举第一种方法. 剩下的全都个第二种方法. 看看能组成多少个队伍就可以了. [代码] #include <bits/stdc+ ...

  9. 杭电5137How Many Maos Does the Guanxi Worth

    How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/5 ...

  10. 位运算(&amp;、|、^)与逻辑运算(&amp;&amp;、 ||)差别

    刚无意在一篇文章中看到了位运算(&.|)和逻辑运算(&&.||)的介绍.想起了自己薄弱的基础知识.于是百度了几把总结了下. 首先从概念上区分下,位运算是将运算符两边的数字换算成 ...