题目

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

You should answer q queries, the i-th query is to find the shortest distance between vertices \(u_i\) and \(v_i\).

输入格式

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 \(v_i,u_i,d_i (1≤u_i,v_i≤n,1≤d_i≤10^9,u_i≠v_i)\). 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≤10^5)\) — the number of queries.

Each of the next q lines contains two integers \(u_i\) and \(v_i (1≤u_i,v_i≤n)\) — descriptions of the queries.

Pay attention to the restriction \(m−n ≤ 20\).

输出格式

Print q lines.

The i-th line should contain the answer to the i-th query — the shortest distance between vertices \(u_i\) and \(v_i\).

输入样例1

3 3
1 2 3
2 3 1
3 1 5
3
1 2
1 3
2 3

输出样例1

3
4
1

输入样例2

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

输出样例2

7
5
6
7
7
1
2
7

题解

由于\(m−n ≤ 20\), 边和点的数量接近, 所以大部分最短路用lca解决, 剩下的一些没有计算的边, 对它们的顶点重新跑一遍最短路, 然后枚举每一个点, 更新两个目标点之间的最短距离.

代码

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const long long INF = 1e18;
const int N = 100005;
int head[N], tote, f[N][21], deth[N], tmp[100], tot, n, m;
long long dis[N], d[50][N];
bool vis[N];
struct Edge { int to, next, value; } edges[N << 1];
void add(int u, int v, int w) {
edges[++tote]= (Edge){ v, head[u], w}, head[u] = tote;
edges[++tote]= (Edge){ u, head[v], w}, head[v] = tote;
}
priority_queue<pair<long long, int>, vector<pair<long long, int> >, greater<pair<long long, int> > > q;
void dijkstra(int id, int S) {
for (int i = 1; i <= n; ++i) dis[i] = INF, vis[i] = false;
dis[S] = 0;
q.push(make_pair(0, S));
while (!q.empty()) {
int u = q.top().second;
q.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = head[u]; i; i = edges[i].next) {
int v = edges[i].to;
if (dis[v] > dis[u] + edges[i].value) {
dis[v] = dis[u] + edges[i].value;
q.push(make_pair(dis[v], v));
}
}
}
for (int i = 1; i <= n; ++i) d[id][i] = dis[i];
}
void dfs(int u, int fa) {
vis[u] = true;
f[u][0] = fa;
deth[u] = deth[fa] + 1;
for (int i = head[u]; i; i = edges[i].next) {
int v = edges[i].to;
if (v == fa) continue;
if (vis[v]) tmp[++tot] = u, tmp[++tot] = v;
else dis[v] = dis[u] + edges[i].value, dfs(v, u);
}
}
int lca(int u, int v) {
if (deth[u] < deth[v]) swap(u, v);
int d = deth[u] - deth[v];
for (int i = 20; i >= 0; --i)
if (d & (1 << i)) u = f[u][i];
if (u == v) return u;
for (int i = 20; i >= 0; --i)
if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
return f[u][0];
}
inline int input() { int t; scanf("%d", &t); return t; }
int main() {
n = input(), m = input();
for (int i = 1; i <= m; ++i){
int u = input(), v = input(), w = input();
add(u, v, w);
}
dfs(1, 0);
for (int i = 1; i <= n; ++i) d[0][i] = dis[i];
for (int j = 1; j <= 20; ++j)
for (int i = 1; i <= n; ++i) f[i][j] = f[f[i][j - 1]][j - 1];
sort(tmp + 1, tmp + tot + 1);
int j = 1;
for (int i = 2; i <= tot; ++i)
if (tmp[j] != tmp[i]) tmp[++j] = tmp[i];
for (int i = 1; i <= j; ++i) dijkstra(i, tmp[i]);
for(int q = input(); q; q--) {
int u = input(), v = input();
long long ans = d[0][u] + d[0][v] - 2 * d[0][lca(u, v)];
for (int i = 1; i <= j; ++i) ans = min(ans, d[i][u] + d[i][v]);
printf("%lld\n", ans);
}
return 0;
}

CF1051F The Shortest Statement 题解的更多相关文章

  1. 【题解】Luogu CF1051F The Shortest Statement

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

  2. cf1051F. The Shortest Statement(最短路/dfs树)

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

  3. [CF1051F]The Shortest Statement

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

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

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

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

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

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

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

  7. Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement

    1051E. Vasya and Big Integers 题意 给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l, ...

  8. [CF1051F]The Shortest Statement_堆优化dij_最短路树_倍增lca

    The Shortest Statement 题目链接:https://codeforces.com/contest/1051/problem/F 数据范围:略. 题解: 关于这个题,有一个重要的性质 ...

  9. codeforces 1051F The Shortest Statement

    题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...

随机推荐

  1. SaaS权限设计总结

    2年前转到SaaS部门之后期间断断续续做着权限相关的业务,这篇文章主要回顾下过往的设计以及其原因和利弊. 不过因为是线上业务,会省略掉很多细节以及账号体系和权益相关得部分,只讨论权限相关. 本文也不会 ...

  2. HDFS ha 格式化报错:a shared edits dir must not be specified if HA is not enabled.

    错误内容: Formatting using clusterid: CID-19921335-620f-4e72-a056-899702613a6b2019-01-12 07:28:46,986 IN ...

  3. Vue-Cli4.x配置文件路径别名

    一.目录结构 二.配置方法 提示:和package.json同级新建vue.config.js文件(可选文件,默认没有创建). const path = require('path');//引入pat ...

  4. Python抽象类以及元类

    抽象基类: 继承的约束与协议 __doc__ = """ 抽象基类: 继承的约束与协议 # 抽象基类 --- 有点java的味道,也有点golang的味道,继承,协议,接 ...

  5. django——bbs

    今日内容概要 bbs是一个前后端不分离的全栈项目,前端和后端都需要我们自己一步步的完成 表创建及同步 注册功能 forms组件 用户头像前端实时展示 ajax 登陆功能 自己实现图片验证码 ajax ...

  6. throws,throw,try,catch,finally 分别代表什么 意义?

    Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口. 在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例.当一个方法出现异常后便 抛出一个异 ...

  7. 说出 Servlet 的生命周期,并说出 Servlet 和 CGI 的区别。

    Servlet 被服务器实例化后,容器运行其 init 方法,请求到达时运行其 service 方法,service 方法自动派 遣运行与请求对应的 doXXX 方法(doGet,doPost)等,当 ...

  8. MyBatis使用模糊查询用户信息及log4j配置文件详解

    1.1 根据用户名称模糊查询用户信息 根据用户名模糊查询用户信息,只需要我们更改映射文件中的sql语句.其他的内容跟上一篇的内容是一样的 1.2添加根据用户名称模糊查询用户信息的sql语句 实例中是查 ...

  9. CAT12提取surface指标

    介绍 基于表面的形态学分析(VSM)的方法被越来越多的研究者使用.本文主要介绍基于SPM12和CAT12工具包进行ROI-based VSM的处理步骤. 方法 本文数据处理使用的工具是MATLAB,S ...

  10. Flume-1.4.0和Hbase-0.96.0整合

    在使用Flume的时候,请确保你电脑里面已经搭建好Hadoop.Hbase.Zookeeper以及Flume.本文将以最新版的Hadoop-2.2.0.Hbase-0.96.0.Zookeeper-3 ...