这就是个水题。

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

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

我们可以直接断开环上的一条边,然后正常链剖,只要在查询的时候强制走这条边然后取个$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. RAC修改数据库的spfile位置

    RAC修改spfile位置 [root@rac1 ~]# su - oracle [oracle@rac1 ~]$ sqlplus  / as sysdba SQL*Plus: Release 11. ...

  2. dpkg安装工具

    dpkg --info "软件包名" --列出软件包解包后的包名称. dpkg -l --列出当前系统中所有的包.可以和参数less一起使用在分屏查看. (类似于rpm -qa) ...

  3. ajax同步异步

    test.html <a href="javascript:void(0)" onmouseover="testAsync()"> asy.js f ...

  4. ubuntu14.04安装python3.7.1

    https://www.python.org/ftp/python/3.7.1/Python-3.7.1.tgz python3.7.1 提示 ModuleNotFoundError: No modu ...

  5. 使用nagios插件 check_mysql_health 过程中遇到的error

    使用nagios插件 check_mysql_health 过程中遇到的error 1.如果在运行监控mysql插件的时候遇到了error安装以下依赖包就可以解决: yum install perl- ...

  6. sql server中类似oracle中decode功能的函数

    sqlserver 2008 写法 select t.PROJECTNAME, t.BUILDCONTENTSCALE, CASE t.PROJECTLEVEL ' THEN '国家重点' ' THE ...

  7. Hyperledger Fabric快速上手

    安装go curl -O https://storage.googleapis.com/golang/go1.10.2.linux-amd64.tar.gz tar -xvf go1.10.2.lin ...

  8. Annotation之三:自定义注解示例,利用反射进行解析

    @Retention定义了该Annotation被保留的时间长短有3中RetentionPolicy.SOURCE源文件有效,RetentionPolicy.CLASS:在class文件中有效,Ret ...

  9. Spring缓存源码剖析:(一)工具选择

    从本篇开始对Spring 4.3.6版本中Cache部分做一次深度剖析.剖析过程中会对其中使用到的设计模式以及原则进行分析.相信对设计内功修炼必定大有好处. 一.环境及工具 IntelliJ IDEA ...

  10. python开发面向对象进阶:反射&内置函数

    isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象或者子类的对象 class Foo(object): pass class ba ...