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. PhoneGap Geolocation结合百度地图api获取地理位置api

    一.使用百度地图API 1.地址:http://developer.baidu.com/map/ 2.在js DEMO中获取反地址解析的DEMO 3.修改这个DEMO的密钥,去创建应用就能创建密钥,然 ...

  2. idea中使用maven

    转:https://www.cnblogs.com/kagome2014/p/8431064.html 对于新版的IDEA可以直接打开Maven项目,但是对于旧版的IDEA需要使用Maven命令生成项 ...

  3. PHP-------抽象和接口

    静态的关键字是:static Class ren { Public static $yanse;    //yanse是一个静态的成员 Static function show() ; // stat ...

  4. springmvc(5)拦截器

    1.什么是拦截器 是指通过统一的拦截从浏览器发送到服务器的请求来完成相应服务增强 2.拦截器的基本原理 可以通过配置过滤器解决乱码问题 和过滤器非常相似 3.搭建工程 注意jar包 此时的工程是完成后 ...

  5. 自定义的打印语句NSLog在控制台输出不完整的完美解决

    // 打印日志 debug #ifdef DEBUG // 调试状态, 打开LOG功能 #define APPLog( s, ... ) printf("class: <%p %s:( ...

  6. mysql忘记密码重置密码方法

    https://blog.csdn.net/weidong_y/article/details/80493743

  7. mysql的入门基本使用(适合新手学习)

    登陆Mysql数据库mysql -u root -p 展示(查询)所有数据库show databases;进入数据库use dataname;创建数据库create database dataname ...

  8. .net core运行环境搭建 linux + windows

    ---------------------------------------linux------------------------------------------------- 一.添加do ...

  9. 如何在 Mac 上卸载 Java?

    使用终端卸载 Oracle Java 注:要卸载 Java,您必须具有管理员权限,并且必须以 root 用户身份或者使用 sudo 工具来执行删除命令. 按照下面所示,删除一个目录和一个文件(符号链接 ...

  10. 几行代码实现iOS摇一摇功能

    实现这个功能很简单,我们直接看代码 - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{ NSLog(@&quo ...