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. c++11 多线程新特性学习 (1) 管理线程

    1.基础介绍 c++11中,线程是通过std::thread对象来开始的,用法为 #include<thread> //必须包含的头文件 void do_work(){ std::cout ...

  2. Linux系统中while管道的

    因为项目从AIX系统迁移到了RedHat系统,之前写过的一段Shell脚本不能成功运行,经过分析,锁定了关键代码如下: readFileContent(){ currentFile=$ fileSho ...

  3. perl的一些小函数——split、join、sort

    有时候,我们需要将一个字符串或一行文本通过某种方式转换为单个的元素存储在数组中,或者将许多元素通过某种分割符,将他们组合成一个字符串.perl刚好就提供了这样的功能,通过split或者join分割或组 ...

  4. 安卓渗透测试工具Drozer学习笔记

    下载,并安装. pip安装即可,安装完成后可能会出现缺少twisted依赖库的问题 ➜ vul git:(master) ✗ drozer console connect drozer Server ...

  5. logback配置详解和使用

    最近知道一种打印日志的新方法,在此做一下学习总结. 转自:行走在云端的愚公 https://www.cnblogs.com/warking/p/5710303.html 一.logback的介绍   ...

  6. (CodeForces - 5C)Longest Regular Bracket Sequence(dp+栈)(最长连续括号模板)

    (CodeForces - 5C)Longest Regular Bracket Sequence time limit per test:2 seconds memory limit per tes ...

  7. HDU 1029 Ignatius and the Princess IV (map的使用)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1029 Ignatius and the Princess IV Time Limit: 2000/10 ...

  8. c++构造函数详解(转)

    c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初 ...

  9. Intermediate_JVM 20180306 : 运行时数据区域

    Java比起C++一个很大的进步就在于Java不用再手动控制指针的delete与free,统一交由JVM管理,但也正因为如此,一旦出现内存溢出异常,不了解JVM,那么排查问题将会变成一项艰难的工作. ...

  10. 系统优化怎么做-SQL优化

    大家好,这里是「聊聊系统优化 」,并在下列地址同步更新 博客园:http://www.cnblogs.com/changsong/ 知乎专栏:https://zhuanlan.zhihu.com/yo ...