[CF1051F] Shortest Statement
问题描述
You are given a weighed undirected connected graph, consisting of n vertices and m edges.
You should answer q queries, the i-th query is to find the shortest distance between vertices ui and vi.
输入格式
The first line contains two integers n and m (1≤n,m≤105,m−n≤20)— the number of vertices and edges in the graph.
Next m lines contain the edges: the i-th edge is a triple of integers vi,ui,di (1≤ui,vi≤n,1≤di≤109,ui≠vi). This triple means that there is an edge between vertices ui and vi of weight di. It is guaranteed that graph contains no self-loops and multiple edges.
The next line contains a single integer q (1≤q≤105)— the number of queries.
Each of the next q lines contains two integers ui and vi (1≤ui,vi≤n)— descriptions of the queries.
Pay attention to the restriction m−n ≤ 20
输出格式
Print q lines.
The i-th line should contain the answer to the ii-th query — the shortest distance between vertices ui and vi.
样例输入
3 3
1 2 3
2 3 1
3 1 5
3
1 2
1 3
2 3
样例输出
3
4
1
题目大意
给你一个有n个点,m条边的无向连通图。 有q次询问,第i次询问回答从ui到di的最短路的长度。
解析
首先,看到m-n<=20这个条件,意味着边只会比点多20。显然,想要在log(n)时间内查询两点之间的最短路只能是在树上。所以,我们先把原图的最小生成树求出来。两点之间的最短路要么在生成树上,要么会由不在树上的那些非树边得到。非树边最多只有21条,可以对这42个点求单源最短路。对于每次询问,首先查询在树上的最短路,然后枚举非树边的端点,看经过这些非树边是否有更短的路径。
代码
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define N 200005
#define M 200005
using namespace std;
struct Edge{
int u,v,w;
}e[M];
int head[N],ver[M*2],nxt[M*2],edge[M*2],l;
int n,m,q,i,j,fa[N],f[N][20],dep[N],d[N],dis[50][N],cnt;
bool use[M];
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
void insert(int x,int y,int z)
{
l++;
ver[l]=y;
edge[l]=z;
nxt[l]=head[x];
head[x]=l;
}
int my_comp(const Edge &x,const Edge &y)
{
return x.w<y.w;
}
int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void Kruskal()
{
sort(e+1,e+m+1,my_comp);
for(int i=1;i<=n;i++) fa[i]=i;
int cnt=n;
for(int i=1;i<=m;i++){
if(cnt==1) break;
int f1=find(e[i].u),f2=find(e[i].v);
if(f1!=f2){
fa[f1]=f2;
cnt--;
insert(e[i].u,e[i].v,e[i].w);
insert(e[i].v,e[i].u,e[i].w);
use[i]=1;
}
}
}
void dfs(int x,int pre)
{
dep[x]=dep[pre]+1;
f[x][0]=pre;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(y!=pre){
d[y]=d[x]+edge[i];
dfs(y,x);
}
}
}
void init()
{
dfs(1,0);
for(int j=0;(1<<(j+1))<=n;j++){
for(int i=1;i<=n;i++){
if(f[i][j]==0) f[i][j+1]=0;
else f[i][j+1]=f[f[i][j]][j];
}
}
}
int LCA(int u,int v)
{
if(dep[u]>dep[v]) swap(u,v);
int tmp=dep[v]-dep[u];
for(int i=0;(1<<i)<=tmp;i++){
if(tmp&(1<<i)) v=f[v][i];
}
if(u==v) return u;
for(int i=log2(1.0*n);i>=0;i--){
if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
}
return f[u][0];
}
int dist(int x,int y)
{
return d[x]+d[y]-2*d[LCA(x,y)];
}
void Dijkstra(int p,int s)
{
priority_queue<pair<int,int> > q;
memset(dis[p],0x3f,sizeof(dis[p]));
q.push(make_pair(0,s));
dis[p][s]=0;
while(!q.empty()){
int x=q.top().second,d=-q.top().first;
q.pop();
if(d!=dis[p][x]) continue;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(dis[p][y]>dis[p][x]+edge[i]){
dis[p][y]=dis[p][x]+edge[i];
q.push(make_pair(-dis[p][y],y));
}
}
}
}
signed main()
{
n=read();m=read();
for(i=1;i<=m;i++) e[i].u=read(),e[i].v=read(),e[i].w=read();
Kruskal();
init();
for(i=1;i<=m;i++){
if(!use[i]){
insert(e[i].u,e[i].v,e[i].w);
insert(e[i].v,e[i].u,e[i].w);
}
}
for(i=1;i<=m;i++){
if(!use[i]){
Dijkstra(++cnt,e[i].u);
Dijkstra(++cnt,e[i].v);
}
}
q=read();
for(i=1;i<=q;i++){
int x=read(),y=read();
int ans=dist(x,y);
for(j=1;j<=cnt;j++) ans=min(ans,dis[j][x]+dis[j][y]);//用非树边更新最短路
cout<<ans<<endl;
}
return 0;
}
[CF1051F] Shortest Statement的更多相关文章
- 【题解】Luogu CF1051F The Shortest Statement
原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开 ...
- 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, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...
- Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement
1051E. Vasya and Big Integers 题意 给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l, ...
- CF 1051 F. The Shortest Statement
F. The Shortest Statement http://codeforces.com/contest/1051/problem/F 题意: n个点,m条边的无向图,每次询问两点之间的最短路. ...
- Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement
题目链接:The Shortest Statement 今天又在群里看到一个同学问$n$个$n$条边,怎么查询两点直接最短路.看来这种题还挺常见的. 为什么最终答案要从42个点的最短路(到$x,y$) ...
- CF_Edu.#51_Div.2_1051F_The Shortest Statement
F. The Shortest Statement time limit per test:4 seconds memory limit per test:256 megabytes input:st ...
- cf1051F. The Shortest Statement(最短路/dfs树)
You are given a weighed undirected connected graph, consisting of nn vertices and mm edges. You shou ...
随机推荐
- Delphi XE2 之 FireMonkey 入门(41) - 控件基础: TListBox
Delphi XE2 之 FireMonkey 入门(41) - 控件基础: TListBox TScrollBox -> TCustomListBox -> TListBox; 其元素项 ...
- Delphi XE2 之 FireMonkey 入门(39) - 控件基础: TScrollBox、TVertScrollBox、TFramedScrollBox、TFramedVertScrollBox
Delphi XE2 之 FireMonkey 入门(39) - 控件基础: TScrollBox.TVertScrollBox.TFramedScrollBox.TFramedVertScrollB ...
- robot framework断言
一.基础 RobotFramework带有丰富的系统关键,使用时无需导入,直接使用,为写自动化用例带来了极大的方便:不能停留在知道或者是会得程度,只有熟练使用各关键字,才能提升自动化用例的写作效率.下 ...
- CDS究竟是个什么鬼?它直接导致了次贷危机?
周五,中国银行间市场交易商协会就确认了这一消息,信用违约互换(CDS)和信用联结票据(CLN)业务指引在今日正式发布实行. 当然,这则消息在中国普通投资者当中还没引起足够关注,但是在很多人看来CDS这 ...
- mysql --> select * from Employee group by name这样的语法有什么意义?
神奇的mysql才会支持select * from Employee group by name 这种反逻辑的SQL(假定该表非仅name一个列) mysql 的逻辑是:select 的返回字段,如果 ...
- BigDecimal进行加减乘除计算
以前大部分关于查询计算的逻辑是在sql语句中执行的,但是有时候会出现比较复杂的计算情况,需要我们在代码中进行计算,这个时候使用BigDecimal进行计算会很方便. BigDecimal num1 = ...
- MySQL的count(*)性能怎么样?
对于count(主键id)来说,innodb引擎会遍历整张表,把每一行的id值都取出来,返回给server层,server层判断id值不为空,就按行累加 对于count(1)来说,innodb引擎遍历 ...
- 方便测试和调用webservice的工具(转)
现在很多时候我们都会遇到这种情况:自己开发的程序要和其他各种各样的程序进行接口数据交互,这里就用到常用的接口服务的调用,但是有时候为了进行方便的测试,我们可能会写许多测试类等来测试,这样浪费了时间,也 ...
- get与post请求的区别 (面试会问)
get和post请求是HTTP与服务器交互方式,也就是通常所说的风别对服务器资源的增删改查 1. post是修改数据 get是获得数据 GET在浏览器回退时是无害的,而POST会再次提交请求.(面 ...
- 解决Jackson2反序列化LocalDateTime报错
今天在整合redis和spring boot的时候,遇到了一个错误,记录一下. 报错如下: Could not read JSON: Cannot construct instance of `jav ...