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


看到题目第一反应是一道最短路裸题,但是数据范围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. SpringBoot 国际化

    一.配置文件 二.application.properties 文件( 让国际化的文件被 SpringBoot 识别 ) spring.messages.basename=i18n.login 三.h ...

  2. C#中的LINQ 基础

    1.LINQ的数据源 必须可枚举的,即必须是数组或者集合 (继承了IEnumerable<T>接口就可以,注意是IEnumerable<T>,不是IEnumerable接口,不 ...

  3. 多校第二场 1004 hdu 5303 Delicious Apples(背包+贪心)

    题目链接: 点击打开链接 题目大意: 在一个周长为L的环上.给出n棵苹果树.苹果树的位置是xi,苹果树是ai,苹果商店在0位置,人的篮子最大容量为k,问最少做多远的距离可以把苹果都运到店里 题目分析: ...

  4. 17 facade

    客户不须要内部的实现,仅仅须要知道有这个功能就好了,(最少知识原则)

  5. 王立平--poser

    Poser是Metacreations公司推出的一款lemmaId=234814&ss_c=ssc.citiao.link" style="color:rgb(51,102 ...

  6. 非Qt工程使用Qt的信号槽机制

    非Qt工程,使用Qt的信号槽机制,蛋疼不?反正我现在就是要做这样一件蛋疼的事. 要使用Qt的信号槽机制,下面是从Qt Assist里面关于 signal & slots 的一句介绍: All ...

  7. bzoj3998: [TJOI2015]弦论(SAM+dfs)

    3998: [TJOI2015]弦论 题目:传送门 题解: SAM的入门题目(很好的复习了SAM并加强Right集合的使用) 其实对于第K小的字符串直接从root开始一通DFS就好,因为son边是直接 ...

  8. 客户端通过wcf来启动或者停止服务器上的windows service

    1.设置服务器上的windows service的security,下面的命令只能用cmd.exe来运行(以管理员模式) sc sdset "LISA_43_Dev_Batch" ...

  9. 升级Xcode8后的相机crash问题-IOS10权限问题

    当我升级到Xcode8后,启动我的相机项目,直接crash,输出的日志如下: '2016-07-08 16:41:11.268943 project-name[362:56625] [MC] Syst ...

  10. Maven 学习笔记(一)

    定义 Maven 是基于项目对象模型(POM)的软件项目管理工具,它采用纯 java 编写,用于管理项目的构建,最早在 Jakata Turbine 项目中开始被使用.它包含了一个项目对象模型(Pro ...