题目链接

分析:

  还是很明白的题意,直接分析问题,首先,这一题真的是给spfa用武之地,m比n大不超过20,但是这并不能使暴力不t,我们考虑一下如何改进一下,我们这样想,这个图只比它的生成树多最多21条边,而树上的最短路有是那么的容易(lca),我们可以先求出在树上两个点之间的最短路,可是非树边也很有可能通过啊,怎么办呢?我们可以这样想,通过至少一个非树边与只通过树边是对立的,也就是说除了只通过非树边的都通过树边,而只通过树边的很好求,下面我们来思考如何求通过至少一个非树边的路径。

  如果通过至少一个非树边,那么一定通过这个边的两个顶点那么就好办了,最多一共有42个顶点在非树边两边,直接枚举通过每一个就好了(当然要提前处理出这些顶点的单元最短路)。

  还有,这题spfa好像是比dij快(m-n<=20)。

代码(dij)

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int maxn=1e5+;
struct E{
int to;
int next;
long long val;
int f;
E(){
f=;
}
}ed[maxn*];
int head[maxn];
int tot;
void J(int a,int b,long long c){
tot++;
ed[tot].to=b;
ed[tot].val=c;
ed[tot].next=head[a];
head[a]=tot;
}
int vis[maxn];
int t[maxn][];
long long va[maxn][];
int js;
int a[maxn];
int b[maxn];
long long c[maxn];
int de[maxn];
void Dfs(int x,int fa,int id){
de[x]=de[fa]+;
t[x][]=fa;
va[x][]=ed[id].val;
for(int i=;i<=;i++){
t[x][i]=t[t[x][i-]][i-];
va[x][i]=va[x][i-]+va[t[x][i-]][i-];
}
vis[x]=;
for(int i=head[x];i;i=ed[i].next){
if(ed[i].to==fa||ed[i].f)
continue;
if(vis[ed[i].to]){
ed[i].f=ed[i%?(i+):(i-)].f=;
js++;
a[js]=x;
b[js]=ed[i].to;
c[js]=ed[i].val;
continue;
}
Dfs(ed[i].to,x,i);
}
}
long long dis[][maxn];
int vis2[maxn];
int ha;
struct Node{
int x;
long long dis;
Node(){
}
Node(int a,long long b){
x=a;
dis=b;
}
friend bool operator < (Node a,Node b){
return a.dis>b.dis;
}
};
priority_queue<Node> q;
void dij(int s){
memset(vis2,,sizeof(vis2));
ha++;
dis[ha][s]=;
q.push(Node(s,));
while(!q.empty()){
Node js=q.top();
q.pop();
if(vis2[js.x])
continue;
vis2[js.x]=;
for(int i=head[js.x];i;i=ed[i].next)
if(dis[ha][ed[i].to]>dis[ha][js.x]+ed[i].val){
dis[ha][ed[i].to]=dis[ha][js.x]+ed[i].val;
q.push(Node(ed[i].to,dis[ha][ed[i].to]));
}
}
}
long long lca(int x,int y){
long long ans=;
if(de[x]<de[y])
swap(x,y);
int k=de[x]-de[y];
int ji=;
while(k){
if(k&){
ans+=va[x][ji];
x=t[x][ji];
}
k>>=;
ji++;
}
if(x==y)
return ans;
for(int i=;i>=;i--)
if(t[x][i]!=t[y][i]){
ans+=va[x][i];
ans+=va[y][i];
x=t[x][i];
y=t[y][i];
}
ans+=va[x][]+va[y][];
return ans;
}
long long Min(long long a,long long b){
return a>b?b:a;
}
int main(){
memset(dis,0x3f,sizeof(dis));
int n,m;
scanf("%d%d",&n,&m);
int js1,js2;
long long js3;
for(int i=;i<=m;i++){
scanf("%d%d%lld",&js1,&js2,&js3);
J(js1,js2,js3);
J(js2,js1,js3);
}
Dfs(,,);
for(int i=;i<=js;i++){
dij(a[i]);
dij(b[i]);
}
int q;
scanf("%d",&q);
for(int i=;i<=q;i++){
scanf("%d%d",&js1,&js2);
long long p=lca(js1,js2);
for(int j=;j<=*js;j++)
p=Min(dis[j][js1]+dis[j][js2],p);
printf("%lld\n",p);
}
return ;
}

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

  1. CF1051F The Shortest Statement 题解

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

  2. 【题解】Luogu CF1051F The Shortest Statement

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

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

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

  4. codeforces 1051F The Shortest Statement

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

  5. The Shortest Statement CodeForces - 1051F(待测试)

    #include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...

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

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

  7. CF 1051 F. The Shortest Statement

    F. The Shortest Statement http://codeforces.com/contest/1051/problem/F 题意: n个点,m条边的无向图,每次询问两点之间的最短路. ...

  8. Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement

    题目链接:The Shortest Statement 今天又在群里看到一个同学问$n$个$n$条边,怎么查询两点直接最短路.看来这种题还挺常见的. 为什么最终答案要从42个点的最短路(到$x,y$) ...

  9. CF_Edu.#51_Div.2_1051F_The Shortest Statement

    F. The Shortest Statement time limit per test:4 seconds memory limit per test:256 megabytes input:st ...

  10. 题解 CF1051F 【The Shortest Statement】

    这道题思路比较有意思,第一次做完全没想到点子上... 看到题目第一反应是一道最短路裸题,但是数据范围1e5说明完全不可能. 这个时候可以观察到题目给出了一个很有意思的条件,就是说边最多比点多20. 这 ...

随机推荐

  1. vim编辑器添加插件NERDTree

    0x01 首先在 http://www.vim.org/scripts/script.php?script_id=1658 下载插件 (可能要爬梯,也可以在https://github.com/scr ...

  2. PHP 安装 XDebug

    下载XDebug扩展 下载对应PHP版本的Xdebug 线程安全(TS)和非线程安全(NTS) 安装Xdebug扩展-php.ini [XDebug] xdebug.profiler_output_d ...

  3. Redis之分布式锁实现

    点赞再看,养成习惯,微信搜索[三太子敖丙]关注这个互联网苟且偷生的工具人. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的 ...

  4. 03-Python基础2

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  5. JavaScript的for循环

    1.循环的目的 什么是循环?循环的目的是什么?循环能做什么? 举一个小例子:武汉疫情,学了JavaScript,必须拿JavaScript干点有意义的事情.我们想告诉武汉:“武汉加油,武汉挺住啊!”. ...

  6. 关于adb的下载和基本使用

    我们无论是开发还是测试,对Android SDK一定都不陌生,如果我们要使用adb(Android debug bridge)命令,那么这个就必不可少了. 1.给大家提供一个下载地址:https:// ...

  7. lei muban

    #include<iostream> using namespace std; template <typename T> class Operator{ public: T ...

  8. c++ vector基本函数、排序、查找用法

    vector用法目录: 1.基本用法 2.vector的删除操作 3.vector的sort排序 4.翻转vector中的所有元素 5.find()函数的用法 6.vector实战(这里写的是我在最开 ...

  9. 多应用下 Swagger 的使用,这可能是最好的方式!

    问题 微服务化的时代,我们整个项目工程下面都会有很多的子系统,对于每个应用都有暴露 Api 接口文档需要,这个时候我们就会想到 Swagger 这个优秀 jar 包.但是我们会遇到这样的问题,假如说我 ...

  10. python中的bytes和str类型

    经过一上午的查找资料.大概理清楚了bytes类型和str类型的区别. bytes类型和str类型在呈现形式有相同之处,如果你print一个bytes类型的变量,会打印一个用b开头,用单引号括起来的序列 ...