codeforces 1051F The Shortest Statement
题目链接:codeforces 1051F The Shortest Statement
题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\)
分析:一开始看这道题:floyd?简单
看下去:\(n\leq 10^5\),有点可怕
接下去:\(q\leq 10^5\),mmp
题目中十分重要的条件是\(m-n\leq 20\),我们要考虑如何利用好它使得能在\(O(logn)\)左右的时间内求出两点间最短路
由于\(m\)和\(n\)相差不大,我们很容易想到一种特殊的图——树,它保证\(m-n=-1\)
在树上求两点之间的最短路是比较容易的:记树上点\(u\)到根节点距离为\(dis(u)\),那么任意两点\((u,v)\)距离就是\(dis(u)+dis(v)-2*dis(lca(u,v))\)
那么我们可以考虑将原来图通过删边转化成一棵树,那么由于条件我们知道我们最多删去21条边,由于每条边都有两个端点,所以最多会影响的点为42个
我们的最短路也可以被分为两种:只走树边或会走非树边,只走树边的话我们直接用上面方法求解,走非树边的话,那么就一定会经过那42个点中的一部分,我们可以将\(u,v\)之间的最短路表示成\(dis(x,u)+dis(x,v)\)(\(x\)属于那42个点)。那么我们可以预处理出那42个点到图中的所有点的最短路,然后枚举这42个点求出最短路
最后对于所有算出的距离取\(min\)即可
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const long long maxd=1e18+7;
struct node{
int to,nxt;
long long cost;
}sq[200500];
struct hnode{
int u;long long dis;
bool operator <(const hnode &p)const{
return dis>p.dis;
}
};
int n,m,q,head[100500],fa[100500][25],low[100500],
dep[100500],all=0,point[200100],cnt=0;
long long dis[50][100500],d[200500];
bool vis[100100];
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
void add(int u,int v,long long w)
{
all++;sq[all].to=v;sq[all].nxt=head[u];sq[all].cost=w;head[u]=all;
}
void dfs(int u,int fu)
{
vis[u]=1;dep[u]=dep[fu]+1;fa[u][0]=fu;
int i;
for (i=1;i<=low[dep[u]];i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for (i=head[u];i;i=sq[i].nxt)
{
int v=sq[i].to;
if (v==fu) continue;
if (vis[v]) {point[++cnt]=u;point[++cnt]=v;}
else
{
d[v]=d[u]+sq[i].cost;
dfs(v,u);
}
}
}
void dij(int id)
{
int i;
for (i=1;i<=n;i++) dis[id][i]=maxd;
memset(vis,0,sizeof(vis));
dis[id][point[id]]=0;
priority_queue<hnode> q;
q.push((hnode){point[id],0});
while (!q.empty())
{
hnode now=q.top();q.pop();
int u=now.u;
if (vis[u]) continue;vis[u]=1;
for (i=head[u];i;i=sq[i].nxt)
{
int v=sq[i].to;
if ((dis[id][v]>dis[id][u]+sq[i].cost))
{
dis[id][v]=dis[id][u]+sq[i].cost;
q.push((hnode){v,dis[id][v]});
}
}
}
}
int LCA(int u,int v)
{
if (dep[u]<dep[v]) swap(u,v);
while (dep[u]>dep[v]) u=fa[u][low[dep[u]-dep[v]]];
if (u==v) return u;
int i;
for (i=low[dep[u]];i>=0;i--)
if (fa[u][i]!=fa[v][i]) {u=fa[u][i];v=fa[v][i];}
return fa[u][0];
}
int main()
{
n=read();m=read();
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
int i;
for (i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
add(u,v,w);add(v,u,w);
}
low[1]=0;dep[0]=0;
for (i=2;i<=n;i++) low[i]=low[i>>1]+1;
dfs(1,0);
sort(point+1,point+1+cnt);
cnt=unique(point+1,point+1+cnt)-point-1;
for (i=1;i<=cnt;i++) dij(i);
q=read();
//for (i=1;i<=n;i++) cout << dep[i] << " ";cout << endl;
while (q--)
{
int u=read(),v=read();
long long ans=d[u]+d[v]-2*d[LCA(u,v)];
for (i=1;i<=cnt;i++) ans=min(ans,dis[i][u]+dis[i][v]);
printf("%I64d\n",ans);
}
return 0;
}
/*
3 3
1 2 3
2 3 1
3 1 5
3
1 2
1 3
2 3
*/
codeforces 1051F The Shortest Statement的更多相关文章
- [Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)
题目链接: https://codeforces.com/contest/1051/problem/F 题目大意: 给出一张$n$个点,$m$条边的带权无向图,多次询问,每次给出$u,v$,要求输出$ ...
- Codeforces.1051F.The Shortest Statement(最短路Dijkstra)
题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...
- 2018.09.24 codeforces 1051F. The Shortest Statement(dijkstra+lca)
传送门 这真是一道一言难尽的题. 首先比赛的时候居然没想出来正解. 其次赛后调试一直调不出来最后发现是depth传错了. 其实这是一道简单题啊. 对于树边直接lca求距离. 由于非树边最多21条. 因 ...
- Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement
1051E. Vasya and Big Integers 题意 给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l, ...
- 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, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...
- Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement
题目链接:The Shortest Statement 今天又在群里看到一个同学问$n$个$n$条边,怎么查询两点直接最短路.看来这种题还挺常见的. 为什么最终答案要从42个点的最短路(到$x,y$) ...
- CF 1051 F. The Shortest Statement
F. The Shortest Statement http://codeforces.com/contest/1051/problem/F 题意: n个点,m条边的无向图,每次询问两点之间的最短路. ...
- 【题解】Luogu CF1051F The Shortest Statement
原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开 ...
随机推荐
- koa-router
为了处理URL,我们需要引入koa-router这个middleware,让它负责处理URL映射. 我们把上一节的hello-koa工程复制一份,重命名为url-koa. 先在package.json ...
- hibernate坑边闲话2
threw exception [Request processing failed; nested exception is org.springframework.orm.hibernate5.H ...
- 009-定时关闭弹出广告窗口 By BoAi 20190414
;~ 定时关闭弹出广告窗口 By BoAi 20190414 ; ### 参数设置段 ######################################SingleInstance,forc ...
- 大神教你Debian GNU/Linux 9.7 “Stretch” Live和安装镜像开放下载
Debian项目团队于昨天发布了Debian GNU/Linux 9 "Stretch" 的第7个维护版本更新,重点修复了APT软件管理器中存在的安全漏洞.在敦促每位用户尽快升级系 ...
- 批量采集世纪佳缘会员图片及winhttp异步采集效率
原始出处:http://www.cnblogs.com/Charltsing/p/winhttpasyn.html 最近老有人问能不能绕过世纪佳缘的会员验证来采集图片,我测试了一下,发现是可以的. 同 ...
- SpringCloud微服务架构分布式组件如何共享session对象
一.简单做一个背景说明1.为说明问题,本文简单微服务架构示例如下 2.组件说明分布式架构,每个组件都是集群或者主备.具体说明如下:zuul service:网关,API调用都走zuul service ...
- node.js介绍和npm的使用
Node.js介绍 打开Nodejs英文网:https://nodejs.org/en/ 中文网:http://nodejs.cn/ 我们会发现这样一句话: 翻译成中文如下: Node.js 是一个基 ...
- ocrosoft 程序设计提高期末复习问题M 递归求猴子吃桃
http://acm.ocrosoft.com/problem.php?cid=1172&pid=12 题目描述 猴子吃桃问题.猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个. ...
- Vmware由于centos升级内核不可运行(C header files matching your running kernel were not found)的解决方案
C header files matching your running kernel were not found. Refer to your distribution's documentati ...
- MySQL查询优化注意下面的四个细节
原文:http://bbs.landingbj.com/t-0-244231-1.html 在任何一个数据库中,查询优化都是不可避免的一个话题.对于数据库工程师来说,优化工作是最有挑战性的工作.MyS ...