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. 关于Java中的反射的一个简单使用

    把以前在其他地方的技术文章重新整理一遍, 方便自己回忆, 也方便他人借鉴. 刚工作的时候发过这么一段代码: package cn.com.hanbinit.test; import java.lang ...

  2. thuwc2018 爆炸记

    从没考过这么差,必须好好总结一下.. $day1$: 上午到了雅礼洋湖,下午就开始考试.. 食堂饭菜还是很不错的,听说都是雅礼自己垫的? 下午的$day1$爆炸了.. 开考以后看了一下三个题,感觉一开 ...

  3. Java程序员从笨鸟到菜鸟之(九十六)深入java虚拟机(五)——java本地接口JNI详解

    http://blog.csdn.net/csh624366188/article/details/8063144 对于Java程序员来说,java语言的好处和优点,我想不用我说了,大家自然会说出很多 ...

  4. 8.spring:事务管理(上):Spring的数据库编程、编程式事务管理

    Spring的数据库编程 Spring框架提供了JDBC模板模式------>JdbcTemplate 简化了开发,在开发中并不经常是使用 实际开发更多使用的是Hibernate和MyBatis ...

  5. Redis配置文件(3)常见的配置修改

    常见的配置: redis.conf 配置项说明如下: 1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程   daemonize no   2. 当Redis以 ...

  6. 第五章.MyBatis高级映射

    5.1   新建数据库准备 CREATE TABLE `finacial_products` ( `product_id` ) NOT NULL AUTO_INCREMENT, `name` ) NO ...

  7. mac 系统安装selenium注意事项

    mac最新系统:OS X EI Captian python: 本机自带的python2.7. (本来想升级3.5,觉得太复杂,放弃了) pip: https://pypi.python.org/py ...

  8. 关于Ftp服务器

    步骤/方法 首先在本地机器上创建一个用户!这些用户是用来登录到FTP的!我的电脑右键->管理->本地用户和组->用户->“右键”新建用户->输入用户名和密码再点创建就行了 ...

  9. [转]超全面的.NET GDI+图形图像编程教程

    本篇主题内容是.NET GDI+图形图像编程系列的教程,不要被这个滚动条吓到,为了查找方便,我没有分开写,上面加了目录了,而且很多都是源码和图片~ GDI+绘图基础 编写图形程序时需要使用GDI(Gr ...

  10. java soa接口测试,可以使用http协议调用

    post调用url:“接口url”+/rpc post调用参数body: { "ver": "接口版本号", "soa":{"re ...