题意

题目链接

题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$

$n, m, q \leqslant 10^5$

Sol

非常好的一道题。

首先建出一个dfs树。

因为边数-点数非常少,所以我们可以对于某些非树边特殊考虑。

具体做法是:对于非树边连接的两个点,暴力求出它们到所有点的最短路

对于询问的$(x, y)$

用树上的边,以及非树边连接的点到他们的最短路之和更新答案

由于边数的限制,非树边连接的点不会超过$2*(m - (n - 1)) = 42$个

#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
#define LL long long
using namespace std;
const int MAXN = * 1e5 + ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
int N, M, Q, head[MAXN], num = , vis[MAXN], fa[MAXN][], dep[MAXN], happen[MAXN];
LL dis[][MAXN], Tdis[MAXN];
vector<int> p;
struct Edge {
LL u, v, w, f, nxt;
}E[MAXN];
inline void AddEdge(int x, int y, int z) {
E[num] = (Edge) {x, y, z, , head[x]};
head[x] = num++;
}
void dfs(int x, int _fa) {
vis[x] = ; dep[x] = dep[_fa] + ;
for(int i = head[x]; ~i; i = E[i].nxt) {
int to = E[i].v;
if(vis[to]) continue;
E[i].f = E[i ^ ].f = ;
Tdis[to] = Tdis[x] + (LL)E[i].w;
fa[to][] = x;
dfs(to, x);
}
}
void Dij(int x, int id) {
memset(dis[id], 0x7f, sizeof(dis[id])); dis[id][x] = ;
memset(vis, , sizeof(vis));
priority_queue<Pair> q; q.push(MP(, x));
while(!q.empty()) {
int p = q.top().se; q.pop();
if(vis[p]) continue;
for(int i = head[p]; ~i; i = E[i].nxt) {
int to = E[i].v;
if(dis[id][to] > dis[id][p] + E[i].w && (!vis[to]))
dis[id][to] = dis[id][p] + E[i].w, q.push(MP(-dis[id][to], to));
}
}
}
void Pre() {
for(int j = ; j <= ; j++)
for(int i = ; i <= N; i++)
fa[i][j] = fa[fa[i][j - ]][j - ];
}
int lca(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if(x == y) return x;
for(int i = ; i >= ; i--)
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][];
}
main() {
// freopen("a.in", "r", stdin);
memset(head, -, sizeof(head));
N = read(); M = read();
for(int i = ; i <= M; i++) {
int x = read(), y = read(), z = read();
AddEdge(x, y, z);
AddEdge(y, x, z);
}
dfs(, );
for(int i = ; i < num; i++)
if(!E[i].f) {
if(!happen[E[i].u]) p.push_back(E[i].u), happen[E[i].u] = ;
if(!happen[E[i].v]) p.push_back(E[i].v), happen[E[i].v] = ;
} for(int i = ; i < p.size(); i++)
Dij(p[i], i);
Pre();
int Q = read();
while(Q--) {
int x = read(), y = read();
LL ans = Tdis[x] + Tdis[y] - * Tdis[lca(x, y)];
for(int i = ; i < p.size(); i++)
ans = min(ans, dis[i][x] + dis[i][y]);
cout << ans << endl;
}
return ;
}

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

  1. 【题解】Luogu CF1051F The Shortest Statement

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

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

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

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

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

  4. CF1051F The Shortest Statement 题解

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

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

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

  6. [CF1051F]The Shortest Statement

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

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

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

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

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

  9. codeforces 1051F The Shortest Statement

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

随机推荐

  1. Ubuntu W: GPG 错误:下列签名无效: BADSIG 84DBCE2DCEC45805 Launchpad PPA fo

    Ubuntu12.04  安装R语言的时候出现的报错. 研究了两个晚上,解决办法如下,跟参考贴有点出入: ############################################### ...

  2. Boost Python学习笔记(三)

    你将学到什么 在C++中调用Python代码时的传参问题 基础类型 继续使用前面的项目,但是先修改下Python脚本(zoo.py),添加Add和Str函数,分别针对整数.浮点数和字符串参数的测试 d ...

  3. restfull知识点

    网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......).因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信.这导致API ...

  4. Codeforces - 77B - Falling Anvils - 几何概型

    https://codeforc.es/contest/77/problem/B 用求根公式得到: \(p-4q\geq0\) 换成熟悉的元: \(y-4x\geq0\) 其中: \(x:[-b,b] ...

  5. shell之hello world

    [root@localhost sh]#vi hello.sh //编辑 .sh 文件 #The first program #!/bin/bash echo 'hello world' [root@ ...

  6. 关于Android模块化我有一些话不知当讲不当讲

    关于Android模块化我有一些话不知当讲不当讲 最近公司一个项目使用了模块化设计,本人参与其中的一个小模块开发,但是整体的设计并不是我架构设计的,开发半年有余,在此记录下来我的想法. 关于Andro ...

  7. [转]Xcode概览:调试应用程序

    原文网址: blog.csdn.net/fhbystudy/article/details/12856261 本文由CocoaChina翻译组成员Creolophus(github主页)翻译自苹果官方 ...

  8. ThinkSNS+ PHP开发概述

    Plus (读音:[plʌs],全称:ThinkSNS+ [θɪŋk es en es plʌs],是 ThinkSNS 系列产品一个重要版本,其软件识别名称为 Plus 即 +) 是一个基于 Lat ...

  9. 数据返回正常 而header头Status=500

    访问接口数据成功返回,但header头Status Code:500,而调用接口的html用ajax访问一直返回500服务器错误,并且ajax一直走error,走不到success中,错误返回状态是连 ...

  10. AT2657 Mole and Abandoned Mine

    传送门 好神的状压dp啊 首先考虑一个性质,删掉之后的图一定是个联通图 并且每个点最多只与保留下来的那条路径上的一个点有边相连 然后设状态:\(f[s][t]\)代表当前联通块的点的状态为\(s\)和 ...