这道题思路比较有意思,第一次做完全没想到点子上。。。


看到题目第一反应是一道最短路裸题,但是数据范围1e5说明完全不可能。

这个时候可以观察到题目给出了一个很有意思的条件,就是说边最多比点多20。

这有什么用呢?

那么我们大胆猜想,可否将整个图划分为21条边(连接最多42个点)和一颗树?(极限情况)

如果这样的话,对于任意的两个节点uv,它们之间的最短路只有两种情况:

  1. 这两个点都在树上。所以说最短路必然是u->lca(u,v)->v。

  2. 不是上面那种情况。这个时候肯定会有连到外面那21个边。我们暴力枚举一下就可以了。

到这里思路就完全出来了,我们先把不属于树的点挑出来,对每一个都跑一下最短路。

然后对于每一组询问判断一下属于哪一种情况就可以了。


AC代码如下:

37657ms 67712kb

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
namespace StandardIO{
template<typename T>inline void read(T &x){
x=0;T f=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
x*=f;
}
template<typename T>inline void write(T x){
if(x<0)putchar('-'),x*=-1;
if(x>=10)write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Solve{
#define int long long
const int N=100100;
const int INF=2147483647;
int n,m,p;
int cnt;
int head[N];
struct node{
int to,val,next;
}edge[N<<1];
template<typename T>inline void add(T a,T b,T c){
edge[++cnt].to=b,edge[cnt].val=c,edge[cnt].next=head[a],head[a]=cnt;
}
struct qnode{
int key,val;
bool operator < (qnode x)const{
return val>x.val;
}
};
int top;
int vis[N],fa[N][23],dist[N],dep[N],q[N];
int dis[50][N];
inline void dfs(int now,int father){
vis[now]=1,fa[now][0]=father;
for(register int i=head[now];i;i=edge[i].next){
int to=edge[i].to;
if(to==father)continue;
if(vis[to])q[++top]=now,q[++top]=to;
else{
dep[to]=dep[now]+1,dist[to]=dist[now]+edge[i].val;
dfs(to,now);
}
}
}
template<typename T>inline T lca(T x,T y){
if(dep[x]<dep[y])swap(x,y);
for(register int i=19;i>=0;--i){
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
}
if(x==y)return x;
for(register int i=19;i>=0;--i){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i],y=fa[y][i];
}
}
return fa[x][0];
}
inline void dijkstra(int now){
memset(dis[now],63,sizeof(dis[now]));
memset(vis,0,sizeof(vis));
priority_queue<qnode>Q;
dis[now][q[now]]=0;
Q.push((qnode){q[now],0});
while(!Q.empty()){
int tmp=Q.top().key;Q.pop();
if(vis[tmp])continue;
vis[tmp]=1;
for(register int i=head[tmp];i;i=edge[i].next){
int to=edge[i].to;
if(!vis[to]&&dis[now][tmp]+edge[i].val<dis[now][to]){
dis[now][to]=dis[now][tmp]+edge[i].val;
Q.push((qnode){to,dis[now][to]});
}
}
}
}
inline void solve(){
read(n),read(m);
for(register int i=1;i<=m;++i){
int a,b,c;
read(a),read(b),read(c);
add(a,b,c),add(b,a,c);
}
dep[1]=1,dfs(1,0);
for(register int j=1;j<=19;++j){
for(register int i=1;i<=n;++i){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
sort(q+1,q+top+1);top=unique(q+1,q+top+1)-q-1;
for(register int i=1;i<=top;++i)dijkstra(i);
read(p);
while(p--){
int x,y;
read(x),read(y);
int ans=dist[x]+dist[y]-2*dist[lca(x,y)];
for(register int i=1;i<=top;++i)ans=min(ans,dis[i][x]+dis[i][y]);
write(ans),putchar('\n');
}
}
}
using namespace Solve;
#undef int
int main(){
solve();
}

题解 CF1051F 【The Shortest Statement】的更多相关文章

  1. 【题解】Luogu CF1051F The Shortest Statement

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

  2. CF1051F The Shortest Statement 题解

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

  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

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

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

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

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

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

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

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

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

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

  9. [CF1051F]The Shortest Statement_堆优化dij_最短路树_倍增lca

    The Shortest Statement 题目链接:https://codeforces.com/contest/1051/problem/F 数据范围:略. 题解: 关于这个题,有一个重要的性质 ...

  10. codeforces 1051F The Shortest Statement

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

随机推荐

  1. 用Python图像处理

    前几天弄了下django的图片上传,上传之后还需要做些简单的处理,python中PIL模块就是专门用来做这个事情的. 于是照葫芦画瓢做了几个常用图片操作,在这里记录下,以便备用. 这里有个字体文件,大 ...

  2. 人脸识别中的harr特征提取(转)

    影响AdaBoost人脸检测训练算法速度很重要的两方面是特征选取和特征计算.选取的特征为矩特征为Haar特征,计算的方法为积分图. (1)Haar特征:     Haar特征分为三类:边缘特征.线性特 ...

  3. 使用IO,递归打印目录树

    package chengbaoDemo; import java.io.File; import java.io.IOException; public class TestIOFile { pub ...

  4. Tsinsen A1206. 小Z的袜子

    /* Tsinsen A1206. 小Z的袜子 http://www.tsinsen.com/new/A1206 BZOJ 2038: [2009国家集训队]小Z的袜子(hose) http://ww ...

  5. unity坐标转换问题

    unity最经常使用的几种坐标.屏幕坐标.世界坐标.ngui坐标,相对于父物体的坐标(localPoisition). 可是有时候这几种坐标相互转换何其困难,让自己狠抓头. 不得不操作的方式是创建虚拟 ...

  6. js 回调函数小例子

    js 回调函数小例子 <script> //将函数作为另一个函数的参数 function test1(){ alert("我是test1"); } function t ...

  7. Centos7 minimal 系列之NAT联网(一)

    一.安装 参考:http://m.blog.csdn.net/qq_24879495/article/details/77838512 二.解决不能联网问题 打开网络共享中心,设置虚拟网卡 编辑虚拟机 ...

  8. 今天,你Try-Catch了吗?

    引言: 高级语言中的异常处理很好用,对于有可能出错的代码我们用Try-Catch包起来,就能保证系统健壮的运行了,但是你的Try-Catch用对了吗? 今天code review的时候,老板给我提了个 ...

  9. vue入门--简单嵌套路由的一个路径小问题

    假设现在有一个项目,刚进去要显示main页面下的contorl页面,那么路由里面的初级路由应该是{main和err},这两个是同一级,然后{control和set}是main下的子路由,foot是这两 ...

  10. 微信小程序 | 小程序的转发问题

    1.配置小程序页面静态转发信息 关于小程序转发问题,文档 在 page 页面填加了该监听函数,会在小程序右上角 ... 菜单中显示“转发”按钮: 监听函数需要 return {} 其中的内容配置转发信 ...