题目链接

分析:

  还是很明白的题意,直接分析问题,首先,这一题真的是给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. 从源码研究如何不重启Springboot项目实现redis配置动态切换

    上一篇Websocket的续篇暂时还没有动手写,这篇算是插播吧.今天讲讲不重启项目动态切换redis服务. 背景 多个项目或微服务场景下,各个项目都需要配置redis数据源.但是,每当运维搞事时(修改 ...

  2. (三)SQLMap工具-使用选项的操作命令&功能

    目录结构 1.Options(选项) 2.Target(目标) 3.Request(请求) 4.Optimization(优化) 5.Injection(注入) 6.Detection(检测) 7.T ...

  3. vector常用方法

    1.find使用 不同于map(map有find方法),vector本身是没有find这一方法,其find是依靠algorithm来实现的. #include <iostream>#inc ...

  4. 获取Google浏览器保存的密码

    获取Google中保存的密码 直接在浏览器上输入 chrome://settings/passwords

  5. 心有 netty 一点通!

    一.标准的netty线程模型 双池合璧: 1.连接线程池: 连接线程池专门负责监听客户端连接请求,并完成连接的建立(包括诸如握手.安全认证等过程). 连接的建立本身是一个极其复杂.损耗性能的过程,此处 ...

  6. ubuntu12.04 跳过grub选择

    1.修改/etc/grub.d/00_head文件. set timeout=-1 修改成 set timeout = ${GRUB_RECORDFAIL_TIMEOUT:--1} 2.修改/etc/ ...

  7. 数值格式化 NumberFormat、 DecimalFormat、 RoundingMode

    NumberFormat [简介] java.text.NumberFormat extends java.text.Format extends java.lang.Object 实现的接口:Ser ...

  8. @codeforces - 549E@ Sasha Circle

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定两个点集 M 与 S,求是否存在一个圆能够分割两个点集. 原 ...

  9. TensorFlow从0到1之TensorFlow损失函数(12)

    正如前面所讨论的,在回归中定义了损失函数或目标函数,其目的是找到使损失最小化的系数.本节将介绍如何在 TensorFlow 中定义损失函数,并根据问题选择合适的损失函数. 声明一个损失函数需要将系数定 ...

  10. (七)Maven Profile 和 Filtering

    每个项目都会有多套运行环境(开发,测试,正式等等),不同的环境配置也不尽相同(如jdbc.url),借助Jenkins和自动部署提供的便利,我们可以把不同环境的配置文件单独抽离出来,打完包后用对应环境 ...