F - The Shortest Statement

emmm, 比赛的时候没有想到如何利用非树边。

其实感觉很简单。。

对于一个询问答案分为两部分求:

第一部分:只经过树边,用倍增就能求出来啦。

第二部分:经过至少一条非树边, 如果经过一个树边那么必定经过其两个端点,暴力的求出这些端点为起始点的最短路。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
using namespace std; const int N = 2e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ; int n, m, tot, cnt, head[N], f[N][], d[N], depth[N];
LL cost[N][], dis[][N];
bool vis[N]; struct Edge {
int from, to, w, nx;
} edge[N << ]; void add(int u, int v, int w) {
edge[tot].from = u;
edge[tot].to = v;
edge[tot].w = w;
edge[tot].nx = head[u];
head[u] = tot++;
} void Dij(int S, LL d[N]) {
memset(d, INF, N * sizeof(LL));
priority_queue<PLI, vector<PLI>, greater<PLI> > que;
d[S] = ; que.push(mk(, S)); while(!que.empty()) {
int u = que.top().se;
LL dis = que.top().fi; que.pop();
if(dis > d[u]) continue;
for(int i = head[u]; ~i; i = edge[i].nx) {
int v = edge[i].to, w = edge[i].w;
if(dis + w < d[v]) {
d[v] = dis + w;
que.push(mk(d[v], v));
}
}
}
} void dfs(int u, int fa, int w, int deep) {
vis[u] = true; depth[u] = deep;
f[u][] = fa; cost[u][] = w;
for(int j = ; j < ; j++) {
f[u][j] = f[f[u][j-]][j-];
cost[u][j] = cost[f[u][j-]][j-] + cost[u][j-];
}
for(int i = head[u]; ~i; i = edge[i].nx) {
int v = edge[i].to;
if(v == fa) continue;
else if(vis[v]) {
d[cnt++] = u; d[cnt++] = v;
} else dfs(v, u, edge[i].w, deep + );
}
} int getLCA (int u, int v){
if(depth[u] < depth[v]) swap(u, v);
for(int j = ; j >= ; j--)
if(depth[u] - depth[v] >= ( << j))
u = f[u][j]; for(int j = ; j >= ; j--)
if(f[u][j] != f[v][j])
u = f[u][j], v = f[v][j];
return u == v ? u : f[u][];
} LL getDis(int u, int v) {
LL ans = ;
for(int j = ; j >= ; j--)
if(depth[u] - depth[v] >= ( << j))
ans += cost[u][j], u = f[u][j];
return ans;
} int main() {
memset(head, -, sizeof(head));
scanf("%d%d", &n, &m);
for(int i = ; i <= m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w); add(v, u, w);
}
dfs(, , , );
sort(d, d + cnt);
cnt = unique(d, d + cnt) - d; for(int i = ; i < cnt; i++) Dij(d[i], dis[i]); int q; scanf("%d", &q);
while(q--) {
int u, v, lca;
scanf("%d%d", &u, &v);
lca = getLCA(u, v);
LL ans = getDis(u, lca) + getDis(v, lca);
for(int i = ; i < cnt; i++) ans = min(ans, dis[i][u] + dis[i][v]);
printf("%lld\n", ans);
}
return ;
} /*
*/

Educational Codeforces Round 51 (Rated for Div. 2) F - The Shortest Statement 倍增LCA + 最短路的更多相关文章

  1. 【 Educational Codeforces Round 51 (Rated for Div. 2) F】The Shortest Statement

    [链接] 我是链接,点我呀:) [题意] [题解] 先处理出来任意一棵树. 然后把不是树上的边处理出来 对于每一条非树边的点(最多21*2个点) 在原图上,做dijkstra 这样就能处理出来这些非树 ...

  2. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  3. Educational Codeforces Round 71 (Rated for Div. 2)-F. Remainder Problem-技巧分块

    Educational Codeforces Round 71 (Rated for Div. 2)-F. Remainder Problem-技巧分块 [Problem Description] ​ ...

  4. Educational Codeforces Round 51 (Rated for Div. 2) G. Distinctification(线段树合并 + 并查集)

    题意 给出一个长度为 \(n\) 序列 , 每个位置有 \(a_i , b_i\) 两个参数 , \(b_i\) 互不相同 ,你可以进行任意次如下的两种操作 : 若存在 \(j \not = i\) ...

  5. Educational Codeforces Round 51 (Rated for Div. 2)

    做了四个题.. A. Vasya And Password 直接特判即可,,为啥泥萌都说难写,,,, 这个子串实际上是忽悠人的,因为每次改一个字符就可以 我靠我居然被hack了???? %……& ...

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

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

  7. CodeForces Educational Codeforces Round 51 (Rated for Div. 2)

    A:Vasya And Password 代码: #include<bits/stdc++.h> using namespace std; #define Fopen freopen(&q ...

  8. The Shortest Statement(Educational Codeforces Round 51 (Rated for Div.2)+最短路+LCA+最小生成树)

    题目链接 传送门 题面 题意 给你一张有\(n\)个点\(m\)条边的联通图(其中\(m\leq n+20)\),\(q\)次查询,每次询问\(u\)与\(v\)之间的最短路. 思路 由于边数最多只比 ...

  9. Educational Codeforces Round 50 (Rated for Div. 2) F - Relatively Prime Powers(数学+容斥)

    题目链接:http://codeforces.com/contest/1036/problem/F 题意: 题解:求在[2,n]中,x != a ^ b(b >= 2 即为gcd)的个数,那么实 ...

随机推荐

  1. python学习(八)定制类和枚举

    `python`定制类主要是实现特定功能,通过在类中定义特定的函数完成特定的功能. class Student(object): def __init__(self, name): self.name ...

  2. C++调用函数模仿数字钟表

    调用系统函数,可以得到系统时间 #include<iostream> #include<windows.h> #include<time.h> using name ...

  3. c#代码访问https服务器以及https的webservice

    代码访问https类似浏览器操作 1.验证证书 2.如果要求客户端证书,提供客户端证书 具体代码如下: 访问https的web public static void ProcessRequest() ...

  4. Hibernate学习(3)- *.hbm.xml详解

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBL ...

  5. Xamarin Error:Could not find android.jar for API Level 23.

    背景:打开别人Xamarin项目找不到android.jar文件 报错: 解决方案1:工具——Android——Amdroid SDK 管理器…出现以下窗口(根据需要的[API级别])勾选相应的Pla ...

  6. NOIP模拟5

    期望得分:100+100+100=300 实际得分:72+12+0=84 T1  [CQOI2009]中位数图 令c[i]表示前i个数中,比d大的数与比d小的数的差,那么如果c[l]=c[r],则[l ...

  7. Python学习笔记(十)匿名函数

    摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431843456 ...

  8. CodeForces - 1004C

    Since Sonya is interested in robotics too, she decided to construct robots that will read and recogn ...

  9. jq消除网页滚动条

    网页有些时候需要能滚动的效果,但是不想要滚动条,我就遇到了这样的需求.自己用jq写了一个垂直滚动条. 纯css也可以实现 .box::-webkit-scrollbar{display:none} 但 ...

  10. 【总结】前端必须收藏的CSS3动效库!!!

    现在的网站和App的设计中越来越重视用户体验,而优秀的动效则能使你的应用更具交互性,从而吸引更多用户的使用. 如果你对CSS3中定义动效还不熟练,或希望采用更加简单直接的方式在你的应用中引入动效的话, ...