P4949 最短距离(树剖)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4949 最短距离(树剖)相关的知识,希望对你有一定的参考价值。
P4949 最短距离(树剖)
n n n个点 n n n条边的无向连通图,显然就是基环树。
考虑断掉环上的一条边,就是树,然后用树剖处理。
无向图判环,并查集即可。
边权转点权,赋给儿子即可,因为每个儿子父亲唯一。
树剖后,转化为区间问题,考虑用BIT。
单点修改,对于断开的那条边直接修改,否则单点修改。
链查询,转化为区间查询即可,注意最后不要加上LCA的那个点权,因为点权是指向父边的,不在查询之中。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr)
void Print(int *a,int n)
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
template <typename T> //x=max(x,y) x=min(x,y)
void cmx(T &x,T y)
if(x<y) x=y;
template <typename T>
void cmn(T &x,T y)
if(x>y) x=y;
int n,q;
int cu,cv,cw,cid;
struct TCS //树链剖分(Tree Chain Subdivision)
#define il inline
struct edge
int to,nt,w;
e[N<<1];
int h[N],cnt;
void add(int u,int v,int w)
e[++cnt]=v,h[u],w,h[u]=cnt;
e[++cnt]=u,h[v],w,h[v]=cnt;
int sz[N],fa[N],son[N],top[N],dfn[N],dep[N];
void dfs(int u,int f)
sz[u]=1,fa[u]=f,dep[u]=dep[f]+1;
for(int i=h[u];i;i=e[i].nt)
int v=e[i].to;
if(v==f) continue;
dfs(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
int id,w[N];
void dfs1(int u,int tp,int c)
top[u]=tp,dfn[u]=++id;w[id]=c;
for(int i=h[u];i;i=e[i].nt)
int v=e[i].to;
if(v==son[u])
dfs1(v,tp,e[i].w);break;
//必须先访问重链,不然dfn序有问题
for(int i=h[u];i;i=e[i].nt)
int v=e[i].to;
if(v!=fa[u]&&v!=son[u]) dfs1(v,v,e[i].w);
#define lowbit(x) x&(-x)
int s[N];
int que(int x)
int ans=0;
while(x>=1)
ans+=s[x];
x-=lowbit(x);
return ans;
void upd(int x,int y)
while(x<=n)
s[x]+=y;
x+=lowbit(x);
int que_c(int x,int y)
int ans = 0;
if(x==y) return 0;
while(top[x]!=top[y])
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=que(dfn[x])-que(dfn[top[x]]-1);
x=fa[top[x]];
if(dep[x]<dep[y]) swap(x,y);
ans+=que(dfn[x])-que(dfn[y]);
return ans;
void init()
dfs(1,0),dfs1(1,1,0);
rep(i,2,n) upd(i,w[i]);
int solve(int x,int y)
return min(min(que_c(x,y),que_c(x,cu)+cw+que_c(cv,y)),que_c(x,cv)+cw+que_c(cu,y));
T;
struct E
int u,v,w;
e[N];
int s[N];
int find(int x)
return s[x]==x?x:s[x]=find(s[x]);
int main()
scanf("%d%d",&n,&q);
rep(i,1,n) s[i] = i;
rep(i,1,n)
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
int fu=find(u),fv=find(v);
if(fu==fv)
cu = u,cv = v,cw = w,cid = i;
continue;
s[fu]=fv;
e[i] = u,v,w;
T.add(u,v,w);
T.init();
while(q--)
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
if(x == cid) cw = y;
else
if(T.fa[e[x].u] == e[x].v)
T.upd(T.dfn[e[x].u],y-e[x].w);
else
T.upd(T.dfn[e[x].v],y-e[x].w);
e[x].w = y;
else
//printf("%d---\\n",T.que_c(x,y));
printf("%d\\n",T.solve(x,y));
return 0;
以上是关于P4949 最短距离(树剖)的主要内容,如果未能解决你的问题,请参考以下文章
51nod2621 树上距离一题四解ST表+倍增+Tarjan+树剖
[51nod] 1766树上的最远点对 树的直径 树剖LCA+ST表静态查询