题目:给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路

n≤100000,m≤100000,m-n≤20.

首先看到m-n≤20这条限制,我们可以想到是围绕这个20来做这道题。

即如果我们随便在图上找一棵树,有最多21条非树边,连接最多42个顶点

考虑两点x,yx,y之间的最短路就是某个点到xx和yy的最短路之和

首先对于只走树边的情况,这个点是两点的LCA

如果经过非树边,xx或yy到枚举的这个点的最短路上的最后一条边一定是非树边(如果都是树边的话完全可以转化到一个连接着非树边的点上去)

然后对于所有连接非树边的点都跑一遍最短路,询问时直接枚举这些点取min即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define M 200010
#define int long long
using namespace std;
int read()
{
char ch=getchar();int x=;
while(ch>''||ch<'') ch=getchar();
while(ch<=''&&ch>='') x=x*+ch-'',ch=getchar();
return x;
}
struct point{
int to,next,dis;
}e[M<<];
int n,m,num,Q,top;
int q[M],head[M],deep[M],dist[M];
int dis[][M],fa[M][];
bool vis[M];
struct node{int id,dis;};
bool operator < (node a1,node a2) {return a1.dis>a2.dis;}
void add(int from,int to,int dis)
{
e[++num].next=head[from];
e[num].to=to;
e[num].dis=dis;
head[from]=num;
}
void dfs(int x,int f)
{
vis[x]=true; fa[x][]=f;
for(int i=head[x];i;i=e[i].next)
{
int to=e[i].to;
if(to==f) continue;
if(vis[to]) q[++top]=x,q[++top]=to;
else
{
deep[to]=deep[x]+;
dist[to]=dist[x]+e[i].dis;
dfs(to,x);
}
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
for(int i=;i>=;i--)
if(deep[fa[x][i]]>=deep[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][];
}
void Dijkstra(int id)
{
memset(dis[id],,sizeof(dis[id]));
memset(vis,false,sizeof(vis));
priority_queue<node>Q;
dis[id][q[id]]=;
Q.push((node){q[id],});
while(!Q.empty())
{
int x=Q.top().id;Q.pop();
if(vis[x]) continue;
vis[x]=true;
for(int i=head[x];i;i=e[i].next)
{
int to=e[i].to;
if(!vis[to]&&dis[id][x]+e[i].dis<dis[id][to])
{
dis[id][to]=dis[id][x]+e[i].dis;
Q.push((node){to,dis[id][to]});
}
}
}
}
#undef int
int main()
{
#define int long long
n=read(); m=read();
for(int i=;i<=m;i++)
{
int a=read(),b=read(),c=read();
add(a,b,c); add(b,a,c);
}
deep[]=;dfs(,);
for(int j=;j<=;j++)
for(int i=;i<=n;i++)
fa[i][j]=fa[fa[i][j-]][j-];
sort(q+,q++top); top=unique(q+,q++top)-q-;
for(int i=;i<=top;i++) Dijkstra(i);
Q=read();
while(Q--)
{
int x=read(),y=read();
int ans=dist[x]+dist[y]-*dist[lca(x,y)];
for(int i=;i<=top;i++) ans=min(ans,dis[i][x]+dis[i][y]);
printf("%I64d\n",ans);
}
return ;
}

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

  1. [CF1051F]The Shortest Statement

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

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

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

  3. 【题解】Luogu CF1051F The Shortest Statement

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

  4. boost dijkstra获得两点间的最短路

    需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...

  5. [C++]boost dijkstra获得两点间的最短路

    需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...

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

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

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

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

  8. CF1051F The Shortest Statement 题解

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

  9. AOJ -0189 Convenient Location && poj 2139 Six Degrees of Cowvin Bacon (floyed求任意两点间的最短路)

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=78207 看懂题就好. 求某一办公室到其他办公室的最短距离. 多组输入,n表示 ...

随机推荐

  1. BigDecimal的equals与compareTo

    equals方法的话会不仅会比较值的大小,还会比较两个对象的精确度, compareTo方法则不会比较精确度,只比较数值的大小

  2. 2016上海浦东汽车展览会C+罩杯 车模名单

    只能帮你们到这了

  3. python爬虫实战(1)--爬取糗事百科

    这里利用正则表达式进行匹配,糗事百科是不需要登录的,所以也没必要用到Cookie,另外糗事百科有的段子是附图的,我们把图抓下来图片不便于显示,那么我们就尝试过滤掉有图的段子. 本篇目标 1.抓取糗事百 ...

  4. Mysql GROUP_CONCAT 使用注意事项

    GROUP_CONCAT 函数返回一个字符串结果,该结果由分组中的值连接组合而成,常和 GROUP BY 连用. 如果需要自定义分隔符可以使用 SEPARATOR. 示例: SELECT GROUP_ ...

  5. ruby 【rails在win7_64位操作系统安装】

    gem update --system --source http://production.s3.rubygems.org 安装截图

  6. ps和ai的一些认识

    ps主要是一个后期软件,它很大程度上不是一个创作型的软件,这是它的定位.我觉得李涛老师那句话说的很好,ps是对已有的素材进行加工的.这个已有的素材来源包括但不限于拍照.扫描.数绘板.下载的.如果说你想 ...

  7. 树莓派研究笔记(5)-- FM网络收音机

    1. 安装mpc sudo apt-get install mpd mpc 2.添加流.注意,这里有个坑,如果下面这个地址不能用,那么就无法测试了.建议先下载一个龙卷风或者酷狗网络收音机,然后添加地址 ...

  8. 使用paramiko连接EC2主机

    在亚马逊云上建的主机没有密码,只有一个PEM文件.所以paramiko需要通过该PEM文件登录云主机进行管理 有两种方式,第一种被我注解了 import paramiko ssh = paramiko ...

  9. HDU 5033 Building (维护单调栈)

    题目链接 题意:n个建筑物,Q条询问,问所在的位置,看到天空的角度是多少,每条询问的位置左右必定是有建筑物的. 思路 : 维护一个单调栈,将所有的建筑物和所有的人都放到一起开始算就行,每加入一个人,就 ...

  10. 自动化打包资源混淆集成python实践----资源混淆

    前面自动化打包资源混淆集成python实践----打包一文讲述了四种打包方案,以及美团打包方案.apk注释添加渠道号方案的实现.这里讲集成资源混淆. 1.资源混淆带来的好处: 1)对资源文件起一定的保 ...