题意

题目链接

题意:给出一张无向图,每次询问两点之间的最短路,满足$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. 阶段2-新手上路\项目-移动物体监控系统\Sprint1-声音报警子系统开发\第1节-Sprint Backlog规划

    根据之前的sprint1-声音报警子系统是相对比较大的一个需求,需要把它进一步细化,然后指定sprint Backlog product Backlog是整个产品的功能列表! sprint Backl ...

  2. Makefiles

    A tutorial by example Compiling your source code files can be tedious, specially when you want to in ...

  3. 利用superlance监控supervisor运行状态

    此文已由作者张家裕授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 最近开发问到supervisor管理下的进程重启了,有无办法做到主动通知,楼主最先想到的是superviso ...

  4. Docker 企业级镜像仓库 Harbor 的搭建与维护

    目录 一.什么是 Harbor 二.Harbor 安装 2.1.Harbor 安装环境 2.2.Harbor安装 2.3 配置HTTPS 三.Harbor 的使用 3.1.登录Harbor并使用 3. ...

  5. 与"shark"相关的表达

    The word shark can be used to describe someone who is tricky and uses other people. Shark这个单词可以用来形容一 ...

  6. vue中通过cross-env插件配置三种环境(开发,测试,生产)打包,不用切换api

    1. 话不多说,第一步就是安装必要的插件 npm install cross-env --save 2.修改config里面的参数,这里只展示一个test,其他类似 3.修改package.json ...

  7. Codeforces Beta Round #71 C【KMP+DP】

    Codeforces79C 题意: 求s串的最大子串不包含任意b串: 思路: dp[i]为以i为起点的子串的最长延长距离. 我们可以想到一种情况就是这个 i 是某个子串的起点,子串的长度-1就是最短, ...

  8. Activity有四种加载模式:standard(默认), singleTop, singleTask和 singleInstance

    standard:Activity的默认加载方法,即使某个Activity在Task栈中已经存在,另一个activity通过Intent跳转到该activity,同样会新创建一个实例压入栈中.例如:现 ...

  9. [sql] view plain copy

    [sql] view plain copy CREATE TABLE SYS_USER ( USER_CODE VARCHAR( 36 ) NOT NULL, LOGIN_NAME VARCHAR( ...

  10. WampServer的安装

    首先安装好Microsoft Visual C++ 然后再安装WampServer 安装过程很简单 错误解决 运行后为黄色图标(成功运行应该为绿色图标) 解决办法: 1.80端口是否被占用 你的80端 ...