这就是个水题。

一开始想把整个环找出来断开当一条链,然后其他部分正常链剖,两个点之间的路径如果经过环就考虑一下走哪边更快。

但是这样子还是太麻烦了。

我们可以直接断开环上的一条边,然后正常链剖,只要在查询的时候强制走这条边然后取个$min$就好了。

时间复杂度$O(nlog^2n)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = 1e5 + ; int n, qn, tot = , head[N], ufs[N], sx, sy, sid, pid[N];
int dfsc = , id[N], siz[N], son[N], fa[N], top[N], dep[N];
ll sv, eVal[N], w[N]; struct Edge {
int to, nxt, eid;
ll val;
} e[N << ]; inline void add(int from, int to, int eid, ll val) {
e[++tot].to = to;
e[tot].eid = eid;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} template <typename T>
inline void chkMin(T &x, T y) {
if(y < x) x = y;
} template <typename T>
inline void swap(T &x, T &y) {
T t = x; x = y; y = t;
} int find(int x) {
return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
} void dfs1(int x, int fat, int depth) {
fa[x] = fat, dep[x] = depth, siz[x] = ;
int maxson = -;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
pid[e[i].eid] = y;
eVal[y] = e[i].val;
dfs1(y, x, depth + ); siz[x] += siz[y];
if(siz[y] > maxson)
maxson = siz[y], son[x] = y;
}
} void dfs2(int x, int topf) {
top[x] = topf, w[id[x] = ++dfsc] = eVal[x];
if(!son[x]) return;
dfs2(son[x], topf);
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fa[x] || y == son[x]) continue;
dfs2(y, y);
}
} namespace Bit {
ll s[N]; #define lowbit(p) (p & (-p)) inline void modify(int p, ll v) {
for(; p <= n; p += lowbit(p))
s[p] += v;
} inline ll getSum(int p) {
ll res = 0LL;
for(; p > ; p -= lowbit(p))
res += s[p];
return res;
} inline ll query(int l, int r) {
return getSum(r) - getSum(l - );
} } using namespace Bit; inline ll getDis(int x, int y) {
ll res = 0LL;
for(; top[x] != top[y]; ) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res += query(id[top[x]], id[x]);
x =fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
res += query(id[x] + , id[y]);
return res;
} int main() {
read(n), read(qn);
for(int i = ; i <= n; i++) ufs[i] = i;
for(int i = ; i <= n; i++) {
int x, y; ll v;
read(x), read(y), read(v);
int fx = find(x), fy = find(y);
if(fx != fy) {
ufs[fx] = fy;
add(x, y, i, v), add(y, x, i, v);
} else
sx = x, sy = y, sv = v, sid = i;
} dfs1(, , ), dfs2(, ); /* for(int i = 1; i <= n; i++)
printf("%lld\n", eVal[i]);
printf("\n"); */ for(int i = ; i <= n; i++)
if(w[i]) modify(i, w[i]); for(int op; qn--; ) {
read(op);
if(op == ) {
int x; ll v;
read(x), read(v);
if(x == sid) sv = v;
else {
modify(id[pid[x]], -eVal[pid[x]]);
eVal[pid[x]] = v;
modify(id[pid[x]], v);
}
} else {
int x, y;
read(x), read(y);
ll res = getDis(x, y);
chkMin(res, getDis(x, sx) + getDis(y, sy) + sv);
chkMin(res, getDis(x, sy) + getDis(y, sx) + sv);
printf("%lld\n", res);
}
} return ;
}

Luogu 4949 最短距离的更多相关文章

  1. Luogu 1351 NOIP 2014 联合权值(贪心,计数原理)

    Luogu 1351 NOIP 2014 联合权值(贪心,计数原理) Description 无向连通图 G 有 n 个点,n-1 条边.点从 1 到 n 依次编号,编号为 i 的点的权值为 Wi, ...

  2. Luogu 1979 NOIP 2013 华容道(搜索,最短路径)

    Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...

  3. Luogu 1613 跑路(最短路径,倍增)

    Luogu 1613 跑路(最短路径,倍增) Description 小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零.可是小A偏偏又有赖床的坏毛病.于是 ...

  4. Luogu 1429 平面最近点对 | 平面分治

    Luogu 1429 平面最近点对 题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 ...

  5. [LUOGU] 3959 宝藏

    https://www.luogu.org/problemnew/show/P3959 注意到n非常小,考虑状压/搜索. 发现状压需要枚举起点,跑n次,一个问题是转移不可以以数字大小为阶段了,考虑用d ...

  6. luogu P3393 逃离僵尸岛-搜索剪枝+spfa

    P3393 逃离僵尸岛 题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被 ...

  7. 【原创】洛谷 LUOGU P3371 【模板】单源最短路径

    P3371 [模板]单源最短路径 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出 ...

  8. [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增)

    [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增) 题面 n个点的图,点i和[l[i],i)的所有点连双向边.每次询问(l,r,x)表示x到[l,r]的所有点的最短 ...

  9. 点(x3,y3)到经过点(x1,y1)和点(x2,y2)的直线的最短距离

    /// <summary> /// 点(x3,y3)到经过点(x1,y1)和点(x2,y2)的直线的最短距离 /// </summary> /// <param name ...

随机推荐

  1. iOS UI调试工具 -- UIDebuggingInformationOverlay

    英文原文: http://ryanipete.com/blog/ios/swift/objective-c/uidebugginginformationoverlay/ 无意中看到iOS自带调试工具 ...

  2. CSS命名规范参考及书写注意事项

    CSS书写顺序 *{ /*显示属性*/ display position float clear cursor … /*盒模型*/ margin padding width height /*排版*/ ...

  3. 关于fft后图像的纵轴问题

    fft后如果纵轴是abs后的值,且为双边图像,那么纵轴表示的就是此频率下信号的幅值*N/2的值,也就是说,如果有一正弦信号,幅度为1,假如fft了50个点,那么此信号频率的幅度就是1*50/2=25. ...

  4. Object.prototype.hasOwnProperty()

    hasOwnProperty() 方法会返回一个布尔值,指示对象是否具有指定的属性作为自身(不继承)属性. 语法 obj.hasOwnProperty(prop) 参数 prop 要检测的属性  字符 ...

  5. jmeter --- 测试计划里的元件

    1.线程组 线程组元件是任何一个测试计划的开始点.在一个测试计划中的所有元件都必须在某个线程组下.顾名思义,线程组元件控制JMeter执行你的测试计划时候使用的线程数量.对线程组的控制允许你: 设置线 ...

  6. android中MediaPlayer类的用法

    用法直接看sample package com.turtle920.androidaudioprocess; import android.media.MediaPlayer; import andr ...

  7. JGroups 入门实践

    前言 JGroups是一个开源的纯java编写的可靠的群组通讯工具.其工作模式基于IP多播,但可以在可靠性和群组成员管理上进行扩展.其结构上设计灵活,提供了一种灵活兼容多种协议的协议栈. JGroup ...

  8. Java基础知识复习(二)

    Java 重写(Override)与重载(Overload) 重写 是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变,属于编译时多态.即外壳不变,核心重写! 重写的好处在于子 ...

  9. 从ROS bag文件中提取图像

    从ROS bag文件中提取图像 创建launch文件,如下: export.launch <launch> <node pkg="rosbag" type=&qu ...

  10. 合并石子(dp)

    合并石子 时间限制: 1 Sec  内存限制: 128 MB提交: 7  解决: 7[提交][状态][讨论版][命题人:quanxing] 题目描述 在一个操场上一排地摆放着N堆石子.现要将石子有次序 ...