处理仙人掌 ---> 首先建立出圆方树。则如果询问的两点 \(lca\) 为圆点,直接计算即可, 若 \(lca\) 为方点,则需要额外判断是走环的哪一侧(此时与两个点在环上的相对位置有关。)

#include <bits/stdc++.h>
using namespace std;
#define maxn 200000
#define int long long
#define CNST 20
int n, m, Q, gra[maxn][CNST];
int N, dfn[maxn], low[maxn], timer;
int S[maxn], dis[maxn], bk[maxn];
int dep[maxn], fa[maxn], id[maxn];
int A, B; struct edge
{
int cnp, head[maxn], to[maxn], last[maxn], w[maxn];
edge() { cnp = ; }
void add(int u, int v, int ww)
{
to[cnp] = v, last[cnp] = head[u], w[cnp] = ww, head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], w[cnp] = ww, head[v] = cnp ++;
}
}E1, E2; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void Solve(int u, int v, int w)
{
N ++; int pre = w, ID = ;
bool flag = ;
for(int i = v; i != fa[u]; i = fa[i])
{
S[i] = pre; pre += bk[i];
id[i] = ++ ID;
}
S[N] = S[u]; S[u] = ;
for(int i = v; i != fa[u]; i = fa[i])
E2.add(N, i, min(S[i], S[N] - S[i]));
} void Tarjan(int u)
{
dfn[u] = low[u] = ++ timer;
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i]; if(v == fa[u]) continue;
if(!dfn[v]) bk[v] = E1.w[i], fa[v] = u, Tarjan(v), low[u] = min(low[u], low[v]);
else low[u] = min(low[u], dfn[v]);
if(low[v] > dfn[u]) E2.add(u, v, E1.w[i]);
}
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(fa[v] != u && dfn[v] > dfn[u]) Solve(u, v, E1.w[i]);
}
} void dfs(int u, int ff)
{
gra[u][] = ff; dep[u] = dep[ff] + ;
for(int i = ; i < CNST; i ++) gra[u][i] = gra[gra[u][i - ]][i - ];
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i];
if(v != ff)
bk[v] = E2.w[i], dis[v] = dis[u] + E2.w[i], dfs(v, u);
}
} int LCA(int x, int y)
{
if(dep[x] < dep[y]) swap(x, y);
for(int i = CNST - ; ~i; i --)
if(dep[gra[x][i]] >= dep[y]) x = gra[x][i];
for(int i = CNST - ; ~i; i --)
if(gra[x][i] != gra[y][i]) x = gra[x][i], y = gra[y][i];
A = x, B = y;
return x == y ? x : gra[x][];
} signed main()
{
n = read(), m = read(), Q = read();
for(int i = ; i <= m; i ++)
{
int u = read(), v = read(), w = read();
E1.add(u, v, w);
}
N = n; Tarjan(); dfs(, );
while(Q --)
{
int u = read(), v = read();
int lca = LCA(u, v);
if(lca <= n) printf("%lld\n", dis[u] + dis[v] - * dis[lca]);
else
{
int ans = dis[u] + dis[v] - dis[A] - dis[B];
if(id[A] <= id[B]) swap(A, B);
ans += min(S[A] - S[B], S[lca] - S[A] + S[B]);
printf("%lld\n", ans);
}
}
return ;
}

【题解】Bzoj2125最短路的更多相关文章

  1. [BZOJ2125]最短路(圆方树DP)

    题意:仙人掌图最短路. 算法:圆方树DP,$O(n\log n+Q\log n)$ 首先建出仙人掌圆方树(与点双圆方树的区别在于直接连割边,也就是存在圆圆边),然后考虑点u-v的最短路径,显然就是:在 ...

  2. BZOJ2125 最短路 【仙人掌最短路】

    题目 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. 输入格式 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一 ...

  3. [题解](次短路)luogu_P2865路障(未)

    好像是个不需要vis数组的次短路,跑到收敛,然而给我脑袋弄炸了......到现在还没懂.......究竟次短路应该怎么求a...... 抄题解: #include<bits/stdc++.h&g ...

  4. bzoj2125 最短路

    Description 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. Input 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个 ...

  5. BZOJ2125 最短路 圆方树、倍增

    传送门 对仙人掌建立圆方树,然后对边定权 对于圆点和圆点之间的边,是原来仙人掌上的桥,边权保持不变 对于圆点和方点之间的边,将圆方树看做以一个圆点为根的有根树之后,一个方点的父亲一定是一个圆点.对于这 ...

  6. 2018.07.25 bzoj2125: 最短路(圆方树+倍增)

    传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...

  7. [题解](最短路)luogu_P5122 Fine Dining

    首先理解这里的美味值相当于给你更多时间让你经过这个草垛的, 也就是在经过草垛时可以给你的时间减少w[i],这样能否比最短路不慢 然而我们并不容易知道怎么走才是最好的,所以要想办法避免找这个方案 我们新 ...

  8. [题解](最短路(树))luogu_P5201_short cut

    一开始想着最短路时统计一下到每个点的牛数量,但是没写出来 建最短路树是个不错的想法,正常跑一次最短路,枚举每个点的前驱,如果d[y]==d[x]+w就是树上的一条边,优先连编号小的, 建好树以后做一次 ...

  9. bzoj2125 最短路——仙人掌两点间距离

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 仙人掌!模仿 lyd 的代码写的,也算是努力理解了: 主要分成 lca 在环上和不在环 ...

随机推荐

  1. 【mvrp多协议vlan注册协议给予三种注册方式的验证】

    MVRP 多vlan注册协议给予三种注册模式的配置 一:根据项目需求搭建好拓扑图如下 二:配置: 首先对项目做理论分析,sw1,sw2,sw3所组成的直连网络中,为使不同的PC之间进行通信,按vlan ...

  2. jquery如何获取对应表单元素?

    问题描述:我页面中有这样多个表单,我都是这个定义的,当我点击确定按钮时,此时能够获得相对应的表单对象,我该怎么获取到他的两个值呢? 解决方案: 页面元素 <form id="form1 ...

  3. Windows下安装Mysql5.5.27(社区版)

    所有平台的 MySQL 下载地址为: MySQL 下载. 挑选你需要的 MySQL Community Server 版本及对应的平台. 运行mysql-5.5.27-win32.msi 进入欢迎界面 ...

  4. C# 设置程序最小化到任务栏右下角,鼠标左键单击还原,右键提示关闭程序

    首先设置程序最小化到任务栏右下角 先给窗口添加一个notifyIcon控件 为notifyIcon控件设置ICO图标(不设置图标将无法在任务栏显示) 给notifyIcon控件添加点击事件 然后是最小 ...

  5. R语言学习笔记(二): 类与泛型函数

    类 大多数R对象都是基于S3类(来源于第三代S语言),例如直方图函数hist()输出是一个包含多个组件的列表,它还有一个属性(attribute),用来指定列表的类,即histogram类. 泛型函数 ...

  6. Android使用butterknife注解出现nullPointerException解决

    1.下载butterknife加入到你的libs中,构建到你的项目中,此时还不能注解成功,必须进行2配置 2.选择你的项目右键---->properties----->java compi ...

  7. C# 控制台应用程序输出颜色字体

    最佳解决方案的代码: static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.Green; Console.W ...

  8. MVC中Model 的Key值不建议用非int型

    一次在开发中,key的值用了 byte型,结果插入第一条正常,第二条开始就出错,原因是用byte类型无法实现自动增加1,所以为了方便,建议使用 int型. public virtual byte bk ...

  9. CDH-5.9.2整合spark2

    1.编写目的:由于cdh-5.9.2自带spark版本是spark1.6,现需要测试spark2新特性,需要整合spark2, 且spark1.x和spark2.x可以同时存在于cdh中,无需先删除s ...

  10. ReentrantLock类的hasQueuedPredecessors方法和head节点的含义

    部分启发来源自文章:Java并发编程--Lock PART 1 1.如果h==t成立,h和t均为null或是同一个具体的节点,无后继节点,返回false.2.如果h!=t成立,head.next是否为 ...