cf1051F. The Shortest Statement(最短路/dfs树)
You should answer qq queries, the ii-th query is to find the shortest distance between vertices uiui and vivi.
Input
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 qq lines contains two integers uiui and vi (1≤ui,vi≤n)vi (1≤ui,vi≤n) — descriptions of the queries.
Pay attention to the restriction m−n ≤ 20
Output
Print q lines.
The i-th line should contain the answer to the i-th query — the shortest distance between vertices ui and vi.
解题思路:
题目非常良心地强调了m-n<=20
建一颗dfs树,对于未加入树的边两端跑Dij
询问只要枚举未入树边更新即可。
代码:
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
struct pnt{
int hd;
int dp;
int no;
int fa[];
lnt dis;
lnt tds;
bool vis;
bool cop;
bool friend operator < (pnt x,pnt y)
{
return x.dis>y.dis;
}
}p[];
struct ent{
int twd;
int lst;
lnt vls;
}e[];
std::priority_queue<pnt>Q;
int n,m;
int q;
int cnt;
int sct;
lnt dist[][];
int sta[];
void ade(int f,int t,lnt v)
{
cnt++;
e[cnt].twd=t;
e[cnt].vls=v;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void Dij(int x)
{
if(p[x].cop)
return ;
p[x].cop=true;
sta[++sct]=x;
for(int i=;i<=n;i++)
{
p[i].dis=0x3f3f3f3f3f3f3f3fll;
p[i].no=i;
p[i].vis=false;
}
p[x].dis=;
while(!Q.empty())
Q.pop();
Q.push(p[x]);
while(!Q.empty())
{
x=Q.top().no;
Q.pop();
if(p[x].vis)
continue;
p[x].vis=true;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].dis>p[x].dis+e[i].vls)
{
p[to].dis=p[x].dis+e[i].vls;
Q.push(p[to]);
}
}
}
for(int i=;i<=n;i++)
dist[sct][i]=p[i].dis;
return ;
}
void dfs(int x,int f)
{
p[x].fa[]=f;
p[x].dp=p[f].dp+;
for(int i=;i<=;i++)
p[x].fa[i]=p[p[x].fa[i-]].fa[i-];
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
if(p[to].tds)
{
Dij(x);
Dij(to);
}else{
p[to].tds=p[x].tds+e[i].vls;
dfs(to,x);
}
}
}
int Lca(int x,int y)
{
if(p[x].dp<p[y].dp)
std::swap(x,y);
for(int i=;i>=;i--)
if(p[p[x].fa[i]].dp>=p[y].dp)
x=p[x].fa[i];
if(x==y)
return x;
for(int i=;i>=;i--)
if(p[x].fa[i]!=p[y].fa[i])
{
x=p[x].fa[i];
y=p[y].fa[i];
}
return p[x].fa[];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ade(a,b,c);
ade(b,a,c);
}
p[].tds=;
dfs(,);
scanf("%d",&q);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int f=Lca(x,y);
lnt ans=p[x].tds+p[y].tds-*p[f].tds;
for(int i=;i<=sct;i++)
ans=std::min(ans,dist[i][x]+dist[i][y]);
printf("%I64d\n",ans);
}
return ;
}
cf1051F. The Shortest Statement(最短路/dfs树)的更多相关文章
- cf1051F. The Shortest Statement(最短路)
题意 题目链接 题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$ $n, m, q \leqslant 10^5$ Sol 非常好的一道题. 首先建出一个dfs树. ...
- 【题解】Luogu CF1051F The Shortest Statement
原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开 ...
- [CF1051F]The Shortest Statement (LCA+最短路)(给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路)
题目:给定一张n个点m条有权边的无向联通图,q次询问两点间的最短路 n≤100000,m≤100000,m-n≤20. 首先看到m-n≤20这条限制,我们可以想到是围绕这个20来做这道题. 即如果我们 ...
- [Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)
题目链接: https://codeforces.com/contest/1051/problem/F 题目大意: 给出一张$n$个点,$m$条边的带权无向图,多次询问,每次给出$u,v$,要求输出$ ...
- [CF1051F]The Shortest Statement
题目大意:给定一张$n$个点$m$条有权边的无向联通图,$q$次询问两点间的最短路 $n\le100000$,$m\le100000$,$1\le100000$,$m$-$n\le20$. 首先看到$ ...
- CF1051F The Shortest Statement 题解
题目 You are given a weighed undirected connected graph, consisting of n vertices and m edges. You sho ...
- Codeforces.1051F.The Shortest Statement(最短路Dijkstra)
题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...
- CF1051F The Shortest Statement Dijkstra + 性质分析
动态询问连通图任意两点间最短路,单次询问. 显然,肯定有一些巧妙地性质(不然你就发明了新的最短路算法了233)有一点很奇怪:边数最多只比点数多 $20$ 个,那么就可以将这个图看作是一个生成树,上面连 ...
- Educational Codeforces Round 51 (Rated for Div. 2) F - The Shortest Statement 倍增LCA + 最短路
F - The Shortest Statement emmm, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...
随机推荐
- java枚举在android项目应用
今天修复一个公司非常早曾经的android应用功能,里面的代码逻辑已经全然错乱,然后发现返回的数据全然不正确了.然后修复了整整两天.然后我又一次整理了一遍,重构就算不上了. 然后就用上了枚举. 什么是 ...
- vue7 下拉列表
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- CentOS中实现与Ubuntu下apt-get install build-essential功能类似的命令
CentOS中实现与Ubuntu下apt-get install build-essential功能类似的命令 在Ubuntu中安装完系统后,可以直接使用apt-get install build-e ...
- 使用PyV8模块破解网站加密cookie
PyV8是Chromium中内嵌的javascript引擎,号称跑的最快.PyV8是用Python在V8的外部API包装了一个python壳,这样便可以使python可以直接与javascript操作 ...
- DEDE 修改后台图集上传单个图片的大小限制
默认情况下,DEDE图集中单个图片大小限制在2M以内,而有时我们需要上传一个2M以上的文件,这是只要修改几个文件就可以实现了. 一.需要修改php.ini这个文件,我们必须保证PHP的配置中允许上传一 ...
- Java main方法中的String[] args
-- Java 命令行参数 -- 关于其中的args以及public static / static public Java 命令行参数 前面已经看到多个使用Java数组的示例,每一个Java应用程序 ...
- BZOJ2137: submultiple(生成函数,二项式定理)
Description 设函数g(N)表示N的约数个数.现在给出一个数M,求出所有M的约数x的g(x)的K次方和. Input 第一行输入N,K.N表示M由前N小的素数组成.接下来N行,第i+1行有一 ...
- 【Henu ACM Round#15 C】 A and B and Team Training
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举第一种方法. 剩下的全都个第二种方法. 看看能组成多少个队伍就可以了. [代码] #include <bits/stdc+ ...
- 杭电5137How Many Maos Does the Guanxi Worth
How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 512000/5 ...
- 位运算(&、|、^)与逻辑运算(&&、 ||)差别
刚无意在一篇文章中看到了位运算(&.|)和逻辑运算(&&.||)的介绍.想起了自己薄弱的基础知识.于是百度了几把总结了下. 首先从概念上区分下,位运算是将运算符两边的数字换算成 ...