这就是个水题。
一开始想把整个环找出来断开当一条链,然后其他部分正常链剖,两个点之间的路径如果经过环就考虑一下走哪边更快。
但是这样子还是太麻烦了。
我们可以直接断开环上的一条边,然后正常链剖,只要在查询的时候强制走这条边然后取个$min$就好了。
时间复杂度$O(nlog^2n)$。
Code:
#include <cstdio> #include <cstring> using namespace std; typedef long long ll; const int N = 1e5 + 25; int n, qn, tot = 0, head[N], ufs[N], sx, sy, sid, pid[N]; int dfsc = 0, 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 << 1]; 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 = 0; char ch = 0; T op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; 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] = 1; int maxson = -1; 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 + 1); 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 > 0; p -= lowbit(p)) res += s[p]; return res; } inline ll query(int l, int r) { return getSum(r) - getSum(l - 1); } } 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] + 1, id[y]); return res; } int main() { read(n), read(qn); for(int i = 1; i <= n; i++) ufs[i] = i; for(int i = 1; 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(1, 0, 1), dfs2(1, 1); /* for(int i = 1; i <= n; i++) printf("%lld ", eVal[i]); printf(" "); */ for(int i = 1; i <= n; i++) if(w[i]) modify(i, w[i]); for(int op; qn--; ) { read(op); if(op == 1) { 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 ", res); } } return 0; }