F. The Shortest Statement

http://codeforces.com/contest/1051/problem/F

题意:

  n个点,m条边的无向图,每次询问两点之间的最短路。(m-n<=20)

分析:

  dijkstra。

  如果是一棵树,那么可以直接通过,dis[u]+dis[v]-dis[lca]*2来求。现在如果建出一棵树,那么非树边只有小于等于21条。

  只经过树边的路径用上面的方式求出,考虑经过非树边的路径。

  经过非树边(至少一条),那么一定经过了这条边的顶点,所以可以对顶点做一次最短路,如果询问u,v经过这个顶点,那么就是dis[u]+dis[v]。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const LL INF = 1e18;
const int N = ; int head[N], nxt[N << ], to[N << ], len[N << ], En;
int f[N][], deth[N], tmp[], tot;
LL dis[N], d[][N];
int n, m;
bool vis[N]; void add_edge(int u,int v,int w) {
++En, to[En] = v, len[En] = w, nxt[En] = head[u], head[u] = En;
++En, to[En] = u, len[En] = w, nxt[En] = head[v], head[v] = En;
} #define pa pair<LL,int>
#define mp(a,b) make_pair(a,b)
priority_queue< pa, vector< pa >, greater< pa > > q; void Dijkstra(int id,int S) {
for (int i=; i<=n; ++i) dis[i] = INF, vis[i] = false;
dis[S] = ;
q.push(mp(, S));
while (!q.empty()) {
int u = q.top().second; q.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i=head[u]; i; i=nxt[i]) {
int v = to[i];
if (dis[v] > dis[u] + len[i]) {
dis[v] = dis[u] + len[i];
q.push(mp(dis[v], v));
}
}
}
for (int i=; i<=n; ++i) d[id][i] = dis[i];
}
void dfs(int u,int fa) {
vis[u] = true;
f[u][] = fa;
deth[u] = deth[fa] + ;
for (int i=head[u]; i; i=nxt[i]) {
int v = to[i];
if (v == fa) continue;
if (vis[v]) tmp[++tot] = u, tmp[++tot] = v;
else dis[v] = dis[u] + len[i], dfs(v, u);
}
}
int LCA(int u,int v) {
if (deth[u] < deth[v]) swap(u, v);
int d = deth[u] - deth[v];
for (int i=; i>=; --i)
if (d & ( << i)) u = f[u][i];
if (u == v) return u;
for (int i=; i>=; --i)
if (f[u][i] != f[v][i])
u = f[u][i], v = f[v][i];
return f[u][];
}
int main() {
n = read(), m = read();
for (int i=; i<=m; ++i) {
int u = read(), v = read(), w = read();
add_edge(u, v, w);
} dfs(, );
for (int i=; i<=n; ++i) d[][i] = dis[i];
for (int j=; j<=; ++j)
for (int i=; i<=n; ++i) f[i][j] = f[f[i][j-]][j-];
sort(tmp + , tmp + tot + );
int lim = tot; tot = ;
for (int i=; i<=lim; ++i) if (tmp[tot] != tmp[i]) tmp[++tot] = tmp[i];
for (int i=; i<=tot; ++i) Dijkstra(i, tmp[i]); int Q = read();
while (Q --) {
int u = read(), v = read();
int t = LCA(u, v);
LL ans = d[][u] + d[][v] - * d[][t];
for (int i=; i<=tot; ++i)
ans = min(ans, d[i][u] + d[i][v]);
printf("%I64d\n",ans);
}
return ;
}

CF 1051 F. The Shortest Statement的更多相关文章

  1. Educational Codeforces Round 51 (Rated for Div. 2) F - The Shortest Statement 倍增LCA + 最短路

    F - The Shortest Statement emmm, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...

  2. Educational Codeforces Round 51 F. The Shortest Statement(lca+最短路)

    https://codeforces.com/contest/1051/problem/F 题意 给一个带权联通无向图,n个点,m条边,q个询问,询问两点之间的最短路 其中 m-n<=20,1& ...

  3. 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 ...

  4. Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement

    1051E. Vasya and Big Integers 题意 给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l, ...

  5. codeforces 1051F The Shortest Statement

    题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...

  6. The Shortest Statement CodeForces - 1051F(待测试)

    #include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...

  7. 【题解】Luogu CF1051F The Shortest Statement

    原题传送门:CF1051F The Shortest Statement 题目大意,给你一个稀疏图,q次查询,查询两点之间距离 边数减点小于等于20 这不是弱智题吗,23forever dalao又开 ...

  8. CF 633 F. The Chocolate Spree 树形dp

    题目链接 CF 633 F. The Chocolate Spree 题解 维护子数答案 子数直径 子数最远点 单子数最长直径 (最长的 最远点+一条链) 讨论转移 代码 #include<ve ...

  9. Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement

    题目链接:The Shortest Statement 今天又在群里看到一个同学问$n$个$n$条边,怎么查询两点直接最短路.看来这种题还挺常见的. 为什么最终答案要从42个点的最短路(到$x,y$) ...

随机推荐

  1. [译] 怎样(以及为什么要)保持你的 Git 提交记录的整洁

    最近在掘金翻译了一篇文章,主要讲的是 Git 提交记录的维护,确实很有用,感兴趣的同学可以去看一下.链接如下: [译] 怎样(以及为什么要)保持你的 Git 提交记录的整洁 截图:

  2. luogu P3941 入阵曲

    嘟嘟嘟 这道题我觉得跟最大子矩阵那道题非常像,都是O(n4)二维前缀和暴力很好想,O(n3)正解需要点转化. O(n4)暴力就不说啦,二维前缀和,枚举所有矩形,应该能得55分. O(n3)需要用到降维 ...

  3. iOS开发之GCD总结

    直接贴出常用的函数,方便要用的时候直接使用. -------------     type 1 ---------------- 说明  : 创建一个dispatch_group_t,每次网络请求前先 ...

  4. mysql使用Navicat 导出和导入数据库

    系统环境: Win7 x64软件准备:Navicat Premium_11.2.7简体中文版下载网址:http://www.cr173.com/soft/419023.html 现在我就向大家介绍 m ...

  5. spring使用Redis自定义前缀后缀名(去掉SimpleKey []+自定义)

    spring中自动加上 SimpleKey [] 解决方案 一.自定义后缀名 1.定义类实现KeyGenerator接口 MyKeyGenerator package com.wbg.springRe ...

  6. 如何用javasript对Gridview的项目进行汇总统计?

    当我们在gridview显示统计信息时,都会想在gridview最后一行显示[小计]结果,但gridview的话好像比较难搞(至少我也不会呀 囧~),那么我就结合jquery写了一个解决方案,下面举个 ...

  7. React-Navigation web前端架构

    React-Navigation 前端架构 准备 /*安装组件*/ npm install --save react-navigation npm install --save react-nativ ...

  8. injection for Xcode10使用方法

    对于一个使用Xcode的使用者来说,麻烦的地方在于使用代码布置界面时候的调试,5s改一下代码,用10s查看修改效果,如果电脑配置稍低,时间更长,这是病,得治,哈哈.下面就来说一下injection的使 ...

  9. chromium之at_exit

    // This class provides a facility similar to the CRT atexit(), except that // we control when the ca ...

  10. exsi6.0远程修改密码

    -------------------------------esxi远程修改root密码--------------------------- 在不接触物理机时,通过启动ssh服务,远程修改密码,具 ...