[CF1051F]The Shortest Statement
题目大意:给定一张$n$个点$m$条有权边的无向联通图,$q$次询问两点间的最短路
$n\le100000$,$m\le100000$,$1\le100000$,$m$-$n\le20$.
首先看到$m$-$n\le20$这条限制,我们可以想到是围绕这个20来做这道题。
即如果我们随便在图上找一棵树,有最多21条非树边,连接最多42个顶点
考虑两点$x,y$之间的最短路就是某个点到$x$和$y$的最短路之和
首先对于只走树边的情况,这个点是两点的$LCA$
如果经过非树边,$x$或$y$到枚举的这个点的最短路上的最后一条边一定是非树边(如果都是树边的话完全可以转化到一个连接着非树边的点上去)
然后对于所有连接非树边的点都跑一遍最短路,询问时直接枚举这些点取$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("%lld\n",ans);
}
return ;
}
[CF1051F]The Shortest Statement的更多相关文章
- 【题解】Luogu CF1051F The Shortest Statement
原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开 ...
- cf1051F. The Shortest Statement(最短路/dfs树)
You are given a weighed undirected connected graph, consisting of nn vertices and mm edges. You shou ...
- CF1051F The Shortest Statement 题解
题目 You are given a weighed undirected connected graph, consisting of n vertices and m edges. You sho ...
- [CF1051F]The Shortest Statement (LCA+最短路)(给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路)
题目:给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路 n≤100000,m≤100000,m-n≤20. 首先看到m-n≤20这条限制,我们可以想到是围绕这个20来做这道题. 即如果我们 ...
- cf1051F. The Shortest Statement(最短路)
题意 题目链接 题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$ $n, m, q \leqslant 10^5$ Sol 非常好的一道题. 首先建出一个dfs树. ...
- CF1051F The Shortest Statement Dijkstra + 性质分析
动态询问连通图任意两点间最短路,单次询问. 显然,肯定有一些巧妙地性质(不然你就发明了新的最短路算法了233)有一点很奇怪:边数最多只比点数多 $20$ 个,那么就可以将这个图看作是一个生成树,上面连 ...
- codeforces 1051F The Shortest Statement
题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...
- The Shortest Statement CodeForces - 1051F(待测试)
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...
- Educational Codeforces Round 51 (Rated for Div. 2) F - The Shortest Statement 倍增LCA + 最短路
F - The Shortest Statement emmm, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...
随机推荐
- Code Forces 26C Dijkstra?
C. Dijkstra? time limit per test 1 second memory limit per test 64 megabytes input standard input ou ...
- window.location下的属性说明
属性 说明 window.location.href 完整的url window.location.protocol 协议 window.location.hostname 主机名 window.lo ...
- Windows平台下解决Oracle12c使用PDB数据库创建SDE的问题 分类: oracle sde 2015-06-12 11:03 88人阅读 评论(0) 收藏
Windows平台下解决Oracle12c使用PDB数据库创建SDE的问题 Oracle 12C中引入了CDB与PDB的新特性,在ORACLE 12C数据库引入的多租用户环境(Multitenant ...
- BSSID,SSID,ESSID区别
SSID(Service Set Identifier) SSID,AP唯一的ID码,许多人认为可以将SSID写成ESSID,其实不然,SSID是个笼统的概念,包含了ESSID和BSSID,用来区 ...
- VMwareWorkstation与Device/CredentialGuard不兼容
win10的虚拟与VMware Workstation的虚拟有冲突,需要关闭win10自带的虚拟Hyper-V功能. 1.Windows键 --- 设置 --- 搜索 “控制面板” --- 程序 - ...
- Linux系统内核参数优化
Linux服务器内核参数优化 cat >> /etc/sysctl.conf << EOF # kernel optimization net.ipv4.tcp_fin_tim ...
- MySQL优化(三):优化数据库对象
二.优化数据库对象 1.优化表的数据类型 应用设计的时候需要考虑字段的长度留有一定的冗余,但不推荐很多字段都留有大量的冗余,这样既浪费磁盘空间,也在应用操作时浪费物理内存. 在MySQL中,可以使用函 ...
- webuploader 多图片上传
WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件. 具体接口参考 webuploader接口文档地址 一.图片上传功能 ...
- Docker给运行中的容器添加映射端口
方法一: 1.获得容器IP将container_name 换成实际环境中的容器名docker inspect `container_name` | grep IPAddress 2. iptables ...
- MySQL5.7密码安全策略(转)
环境介绍:CentOS 6.7 MySQL版本:5.7.11 1.查看现有的密码策略 mysql> SHOW VARIABLES LIKE 'validate_password%';参数解释:1 ...