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, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...
随机推荐
- 微软CEO纳德拉拥抱Linux意欲何为?
"我不喜欢打一场过时的战争."微软 CEO 萨蒂亚·纳德拉说道,"我想要打一场全新的战役." 上周日晚上.萨蒂亚·纳德拉来到旧金山 North Beach 区的 ...
- 离散化求RECT1
本文转载至点击打开链接 #include<stdio.h> struct node{ int x1,y1,x2,y2,c; }; struct node s[1010]; int px[2 ...
- Metasploit - Tips for Evading Anti-Virus
绕过杀毒软件,有很多钟方法.此处介绍一种,编写python程序调用shellcode,并使用Pyinstaler将python程序编译为exe程序. 准备工作:(Windows XP环境下编译) 将P ...
- MySQL 使用自增ID主键和UUID 作为主键的优劣比較具体过程(从百万到千万表记录測试)
主键类型 SQL语句 运行时间 (秒) (1)模糊范围查询1000条数据,自增ID性能要好于UUID 自增ID SELECT SQL_NO_CACHE t.* FROM test.`UC_US ...
- UVALive - 6269 Digital Clock 模拟
UVALive - 6269 Digital Clock 题意:时钟坏了,给你一段连续的时间,问你现在可能的时间是多少. 思路:直接模拟,他妈的居然这场就跪在了这题,卧槽,他妈的就在111行,居然多打 ...
- ORA-01659: 无法分配超出 7 的 MINEXTENTS
plsql连接出错:ORA-01659: 无法分配超出 7 的 MINEXTENTS (在表空间 PERFSTAT 中) 从 Oracle Database 10g Enterprise Editio ...
- mybatis集成到spring理解
- ES6学习笔记(二)变量的解构与赋值
1.数组的解构赋值 1.1基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前,为变量赋值,只能直接指定值. let a = 1 ...
- 生成ssh公有密钥而且注冊到Github Generate ssh rsa keys and register public key on Github
私有密钥和公有密钥是成对的两个文件,私有文件保存在自己的本机,公有密钥保存到还有一端的server,站点等. github就是一种站点. 仅仅有保存了私有密钥的机器才干訪问远程的server等. 使用 ...
- USACO milk
/* ID:kevin_s1 PROG:milk LANG:C++ */ #include <iostream> #include <string> #include < ...