cf1051F. The Shortest Statement(最短路)
题意
题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$
$n, m, q \leqslant 10^5$
Sol
非常好的一道题。
首先建出一个dfs树。
因为边数-点数非常少,所以我们可以对于某些非树边特殊考虑。
具体做法是:对于非树边连接的两个点,暴力求出它们到所有点的最短路
对于询问的$(x, y)$
用树上的边,以及非树边连接的点到他们的最短路之和更新答案
由于边数的限制,非树边连接的点不会超过$2*(m - (n - 1)) = 42$个
#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
#define LL long long
using namespace std;
const int MAXN = * 1e5 + ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
int N, M, Q, head[MAXN], num = , vis[MAXN], fa[MAXN][], dep[MAXN], happen[MAXN];
LL dis[][MAXN], Tdis[MAXN];
vector<int> p;
struct Edge {
LL u, v, w, f, nxt;
}E[MAXN];
inline void AddEdge(int x, int y, int z) {
E[num] = (Edge) {x, y, z, , head[x]};
head[x] = num++;
}
void dfs(int x, int _fa) {
vis[x] = ; dep[x] = dep[_fa] + ;
for(int i = head[x]; ~i; i = E[i].nxt) {
int to = E[i].v;
if(vis[to]) continue;
E[i].f = E[i ^ ].f = ;
Tdis[to] = Tdis[x] + (LL)E[i].w;
fa[to][] = x;
dfs(to, x);
}
}
void Dij(int x, int id) {
memset(dis[id], 0x7f, sizeof(dis[id])); dis[id][x] = ;
memset(vis, , sizeof(vis));
priority_queue<Pair> q; q.push(MP(, x));
while(!q.empty()) {
int p = q.top().se; q.pop();
if(vis[p]) continue;
for(int i = head[p]; ~i; i = E[i].nxt) {
int to = E[i].v;
if(dis[id][to] > dis[id][p] + E[i].w && (!vis[to]))
dis[id][to] = dis[id][p] + E[i].w, q.push(MP(-dis[id][to], to));
}
}
}
void Pre() {
for(int j = ; j <= ; j++)
for(int i = ; i <= N; i++)
fa[i][j] = fa[fa[i][j - ]][j - ];
}
int lca(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[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][];
}
main() {
// freopen("a.in", "r", stdin);
memset(head, -, sizeof(head));
N = read(); M = read();
for(int i = ; i <= M; i++) {
int x = read(), y = read(), z = read();
AddEdge(x, y, z);
AddEdge(y, x, z);
}
dfs(, );
for(int i = ; i < num; i++)
if(!E[i].f) {
if(!happen[E[i].u]) p.push_back(E[i].u), happen[E[i].u] = ;
if(!happen[E[i].v]) p.push_back(E[i].v), happen[E[i].v] = ;
} for(int i = ; i < p.size(); i++)
Dij(p[i], i);
Pre();
int Q = read();
while(Q--) {
int x = read(), y = read();
LL ans = Tdis[x] + Tdis[y] - * Tdis[lca(x, y)];
for(int i = ; i < p.size(); i++)
ans = min(ans, dis[i][x] + dis[i][y]);
cout << ans << endl;
}
return ;
}
cf1051F. The Shortest Statement(最短路)的更多相关文章
- 【题解】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来做这道题. 即如果我们 ...
- 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 ...
- Codeforces.1051F.The Shortest Statement(最短路Dijkstra)
题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...
- [CF1051F]The Shortest Statement
题目大意:给定一张$n$个点$m$条有权边的无向联通图,$q$次询问两点间的最短路 $n\le100000$,$m\le100000$,$1\le100000$,$m$-$n\le20$. 首先看到$ ...
- 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, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...
- codeforces 1051F The Shortest Statement
题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...
随机推荐
- 关于SCANF 与 GETS(C语言)
SCANF遇到空格会自动停止录入字符串,而GETS不会,GETS可以用于输入带空格的字符串
- [转] Hibernate不能自动建表解决办法(hibernate.hbm2ddl.auto) (tables doesn't exist)
转自: http://blog.csdn.net/biangren/article/details/8010018 最近开始学Hibernate,看的是李刚的那本<轻量级java ee企业应用实 ...
- 【转】Subversion快速入门教程-动画演示
如何快速建立Subversion服务器,并且在项目中使用起来,这是大家最关心的问题,与CVS相比,Subversion有更多的选择,也更加的容易,几个命令就可以建立一套服务器环境,可以使用起来,这里配 ...
- hdu1059
#include <stdio.h> #include <string.h> #define MAXN 120005 int main() { int num[7]; int ...
- 定时器详解和应用、js加载阻塞、css加载阻塞
1.setTimeout().setInterval()详解和应用 1.1 详解: setTimeout.setInterval执行时机 1.2 存在问题: setInterval重复定时器可能存在的 ...
- 实现html页面只自动跳转一次
function show(){ var value= sessionStorage.getItem("flg"); if(value==null || value==undef ...
- Yaf + Smarty 整合笔记
Yaf真的是太简单了,简单到使用mvc的时候在view里面需要手写php脚本.因此考虑整合一下smarty模板引擎.随心所欲也正是yaf的魅力 Yaf 安装 这里简单说一下yaf的安装,已经是非常无脑 ...
- Spark SQL 读到的记录数与 hive 读到的不一致
问题:我用 sqoop 把 Mysql 中的数据导入到 hive,使用了--delete-target-dir --hive-import --hive-overwrite 等参数,执行了两次. my ...
- Codevs 2144 砝码称重 2
2144 砝码称重 2 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 有n个砝码,现在要称一个质量为m ...
- bzoj4873: [Shoi2017]寿司餐厅(最小割)
传送门 大佬们是怎么一眼看出这是一个最大权闭合子图的……大佬好强->这里 1.把所有区间$(i,j)$看成一个点,如果权值大于0,则从$S$向他连边,容量为权值,否则从它向$T$连边,容量为权值 ...