题意:给定一个带权边无向基环树,有两种操作,一种是改变某个边的权值,另一种是询问两点间的最短路径。

可以对环进行缩点,以环为根建立一棵新树,并记录与环相连的所有点和环上的哪个点相连,将路径分为环外和环内的两类进行处理。环外的路径可以用树剖+树状数组维护,环内的路径复制一倍,用另一个树状数组维护。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+;
int hd[N],n,m,ne,sta[N],tp,vis[N],id[N],anc[N],lid[N],nl;
int fa[N],son[N],siz[N],dep[N],top[N],bg[N],ed[N],rnk[N],tot;
struct E2 {int u,v,c;} e2[N];
struct E {int v,c,nxt;} e[N<<];
struct BIT {
ll c[N<<];
int n;
int lb(int x) {return x&-x;}
void add(int u,int x) {for(; u<=n; u+=lb(u))c[u]+=x;}
ll get(int u) {ll ret=; for(; u; u-=lb(u))ret+=c[u]; return ret;}
ll sum(int l,int r) {return get(r)-get(l-);}
void init(int _n) {memset(c,,sizeof c),n=_n;}
} tr1,tr2;
void addedge(int u,int v,int c) {e[ne]= {v,c,hd[u]},hd[u]=ne++;}
bool isloop(int u) {return id[u]==n+;}
bool dfs_loop(int u,int f) {
if(vis[u]) {
while(!lid[u]) {
int v=sta[tp--];
id[v]=n+,lid[v]=++nl;
}
return ;
}
vis[u]=,sta[++tp]=u;
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==f)continue;
if(dfs_loop(v,u))return ;
}
tp--;
return ;
}
void dfs_anc(int u,int f,int a) {
anc[u]=a;
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==f||isloop(v))continue;
dfs_anc(v,u,a);
}
}
void dfs_chain_1(int u,int f,int d) {
fa[u]=f,son[u]=,siz[u]=,dep[u]=d;
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==fa[u]||isloop(v))continue;
dfs_chain_1(v,u,d+),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs_chain_2(int u,int tp) {
top[u]=tp,bg[u]=++tot,rnk[bg[u]]=u;
if(son[u])dfs_chain_2(son[u],tp);
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==fa[u]||v==son[u]||isloop(v))continue;
dfs_chain_2(v,v);
}
ed[u]=tot;
}
void upd(int u,int v,int x) {
if(isloop(u)&&isloop(v)) {
int l=lid[u],r=lid[v];
if(l>r)swap(l,r);
if(r-l!=)swap(l,r);
tr2.add(r,-tr2.sum(r,r)),tr2.add(r+nl,-tr2.sum(r+nl,r+nl));
tr2.add(r,x),tr2.add(r+nl,x);
} else {
int l=bg[id[u]],r=bg[id[v]];
if(l>r)swap(l,r);
tr1.add(r,-tr1.sum(r,r)),tr1.add(r,x);
}
}
ll qry_loop(int u,int v) {
int l=lid[u],r=lid[v];
if(l>r)swap(l,r);
return min(tr2.sum(l+,r),tr2.sum(r+,l+nl));
}
ll qry_tree(int u,int v) {
int ancu=anc[u],ancv=anc[v];
u=id[u],v=id[v];
ll ret=;
for(; top[u]!=top[v]; u=fa[top[u]]) {
if(dep[top[u]]<dep[top[v]])swap(u,v);
ret+=tr1.sum(bg[top[u]],bg[u]);
}
if(dep[u]<dep[v])swap(u,v);
ret+=tr1.sum(bg[v]+,bg[u]);
ret+=qry_loop(ancu,ancv);
return ret;
}
int main() {
int T;
for(scanf("%d",&T); T--;) {
memset(hd,-,sizeof hd),ne=tp=nl=tot=;
memset(vis,,sizeof vis);
scanf("%d%d",&n,&m);
for(int i=; i<=n; ++i) {
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c),addedge(v,u,c);
e2[i]= {u,v,c};
}
for(int i=; i<=n; ++i)id[i]=i;
dfs_loop(,),id[n+]=n+;
for(int u=; u<=n; ++u)if(isloop(u))dfs_anc(u,,u);
for(int u=; u<=n; ++u)if(isloop(u)) {
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(!isloop(v))addedge(n+,v,e[i].c);
}
}
dfs_chain_1(n+,,),dfs_chain_2(n+,n+);
tr1.init(tot),tr2.init(nl*);
for(int i=; i<=n; ++i)upd(e2[i].u,e2[i].v,e2[i].c);
while(m--) {
int f,a,b;
scanf("%d%d%d",&f,&a,&b);
if(f==)upd(e2[a].u,e2[a].v,b);
else printf("%lld\n",qry_tree(a,b));
}
}
return ;
}

也可以LCA+差分维护每个点到根节点的距离,复杂度少了个log(但实际速度差不了多少)

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+;
int hd[N],n,m,ne,sta[N],tp,vis[N],id[N],anc[N],lid[N],nl;
int fa[N],son[N],siz[N],dep[N],top[N],bg[N],ed[N],rnk[N],tot;
struct E2 {int u,v,c;} e2[N];
struct E {int v,c,nxt;} e[N<<];
struct BIT {
ll c[N<<];
int n;
int lb(int x) {return x&-x;}
void add(int u,int x) {for(; u<=n; u+=lb(u))c[u]+=x;}
ll get(int u) {ll ret=; for(; u; u-=lb(u))ret+=c[u]; return ret;}
ll sum(int l,int r) {return get(r)-get(l-);}
void init(int _n) {memset(c,,sizeof c),n=_n;}
} tr1,tr2;
void addedge(int u,int v,int c) {e[ne]= {v,c,hd[u]},hd[u]=ne++;}
bool isloop(int u) {return id[u]==n+;}
bool dfs_loop(int u,int f) {
if(vis[u]) {
while(!lid[u]) {
int v=sta[tp--];
id[v]=n+,lid[v]=++nl;
}
return ;
}
vis[u]=,sta[++tp]=u;
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==f)continue;
if(dfs_loop(v,u))return ;
}
tp--;
return ;
}
void dfs_anc(int u,int f,int a) {
anc[u]=a;
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==f||isloop(v))continue;
dfs_anc(v,u,a);
}
}
void dfs_chain_1(int u,int f,int d) {
fa[u]=f,son[u]=,siz[u]=,dep[u]=d;
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==fa[u]||isloop(v))continue;
dfs_chain_1(v,u,d+),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs_chain_2(int u,int tp) {
top[u]=tp,bg[u]=++tot,rnk[bg[u]]=u;
if(son[u])dfs_chain_2(son[u],tp);
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==fa[u]||v==son[u]||isloop(v))continue;
dfs_chain_2(v,v);
}
ed[u]=tot;
}
void upd(int u,int v,int x) {
if(isloop(u)&&isloop(v)) {
int l=lid[u],r=lid[v];
if(l>r)swap(l,r);
if(r-l!=)swap(l,r);
tr2.add(r,x),tr2.add(r+nl,x);
} else {
u=id[u],v=id[v];
if(fa[u]==v)swap(u,v);
tr1.add(bg[v],x),tr1.add(ed[v]+,-x);
}
}
ll qry_loop(int u,int v) {
int l=lid[u],r=lid[v];
if(l>r)swap(l,r);
return min(tr2.sum(l+,r),tr2.sum(r+,l+nl));
}
ll qry_tree(int u,int v) {
int ancu=anc[u],ancv=anc[v];
u=id[u],v=id[v];
ll ret=tr1.get(bg[u])+tr1.get(bg[v]);
for(; top[u]!=top[v]; u=fa[top[u]])
if(dep[top[u]]<dep[top[v]])swap(u,v);
if(dep[u]<dep[v])swap(u,v);
ret-=*tr1.get(bg[v]);
ret+=qry_loop(ancu,ancv);
return ret;
}
int main() {
int T;
for(scanf("%d",&T); T--;) {
memset(hd,-,sizeof hd),ne=tp=nl=tot=;
memset(vis,,sizeof vis);
scanf("%d%d",&n,&m);
for(int i=; i<=n; ++i) {
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c),addedge(v,u,c);
e2[i]= {u,v,c};
}
for(int i=; i<=n; ++i)id[i]=i;
dfs_loop(,),id[n+]=n+;
for(int u=; u<=n; ++u)if(isloop(u))dfs_anc(u,,u);
for(int u=; u<=n; ++u)if(isloop(u)) {
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(!isloop(v))addedge(n+,v,e[i].c);
}
}
dfs_chain_1(n+,,),dfs_chain_2(n+,n+);
tr1.init(tot),tr2.init(nl*);
for(int i=; i<=n; ++i)upd(e2[i].u,e2[i].v,e2[i].c);
while(m--) {
int f,a,b;
scanf("%d%d%d",&f,&a,&b);
if(f==)upd(e2[a].u,e2[a].v,b-e2[a].c),e2[a].c=b;
else printf("%lld\n",qry_tree(a,b));
}
}
return ;
}

HDU - 6393 Traffic Network in Numazu (基环树+树链剖分/LCA)的更多相关文章

  1. hdu 6393 Traffic Network in Numazu (树链剖分+线段树 基环树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6393 思路:n个点,n条边,也就是基环树..因为只有一个环,我们可以把这个环断开,建一个新的点n+1与之相 ...

  2. HDU - 6393 Traffic Network in Numazu(树链剖分+基环树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6393 题意 给n个点和n条边的图,有两种操作,一种修改边权,另一种查询u到v的最短路. 分析 n个点和n条边,实 ...

  3. HDU - 6393 Traffic Network in Numazu (LCA+RMQ+树状数组)

    这道题相当于将这两题结合: http://poj.org/problem?id=2763 http://codeforces.com/gym/101808/problem/K 题意:有N各点N条边的带 ...

  4. Traffic Network in Numazu

    Traffic Network in Numazu 题目描述 Chika is elected mayor of Numazu. She needs to manage the traffic in ...

  5. hdu6393 Traffic Network in Numazu 树链剖分

    题目传送门 题意:给出n个点n条边的无向带权图,再给出两种操作,操作1是将第x条边的边权修改为y,操作2是询问点x到点y的最短路径. 思路:如果是n个点n-1条边,题目就变成了树,修改边权和询问最短路 ...

  6. 【BZOJ 2791】 2791: [Poi2012]Rendezvous (环套树、树链剖分LCA)

    2791: [Poi2012]Rendezvous Description 给定一个n个顶点的有向图,每个顶点有且仅有一条出边.对于顶点i,记它的出边为(i, a[i]).再给出q组询问,每组询问由两 ...

  7. CodeForces 916E Jamie and Tree(树链剖分+LCA)

    To your surprise, Jamie is the final boss! Ehehehe. Jamie has given you a tree with n vertices, numb ...

  8. NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分

    原文链接https://www.cnblogs.com/zhouzhendong/p/9275606.html 题目传送门 - 洛谷P1600 题目传送门 - LOJ#2359 题目传送门 - Vij ...

  9. 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)

    题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...

随机推荐

  1. python 实现 灰色预测 GM(1,1)模型 灰色系统 预测 灰色预测公式推导

    来源公式推导连接 https://blog.csdn.net/qq_36387683/article/details/88554434 关键词:灰色预测 python 实现 灰色预测 GM(1,1)模 ...

  2. RFC3550中文

    RTP:实时应用程序传输协议   摘要 本文描述RTP(real-time transport protocol),实时传输协议.RTP在多点传送(多播)或单点传送(单播)的网络服务上,提供端对端的网 ...

  3. 【Spring 源码】Spring 加载资源并装配对象的过程(XmlBeanDefinitionReader)

    Spring 加载资源并装配对象过程 在Spring中对XML配置文件的解析从3.1版本开始不再推荐使用XmlBeanFactory而是使用XmlBeanDefinitionReader. Class ...

  4. SIFT图像配准 python3.6 + opencv3.3代码

    opencv3.x 中部分函数有改变: 1. SIFT:可以采用help(cv2.xfeatures2d)查询 2.drawKeypoints: 同样采用help()方法查询 opencv3 版本si ...

  5. HTTP协议 django下载安装 url路由分发

    今日内容 HTTP协议 MVC和MTV框架模式 django下载安装 django的url路由分发 HTTP协议 http协议 请求信息格式 GET / HTTP/1.1 请求行 Host: 127. ...

  6. springboot mongodb jpa常用方法整理

    官方文档https://docs.spring.io/spring-data/data-mongodb/docs/current/reference/html/index.html 查询: ***** ...

  7. STM32F10xxx_启动模式

    目录 STM32F10xxx_启动模式 更新记录 启动配置 参考: STM32F10xxx_启动模式 更新记录 version status description date author V1.0 ...

  8. 帝国cms 通过tags给产品或者新闻进行分类

    1.增加TAGS分类 先找到栏目== >TAGS管理 == > 管理TAGS分类 == >增加分类 2.增加相关的tag标签,也要选好TAGS分类 3.增加自定义标签模板 具体怎么写 ...

  9. vue组件之子组件和父组件

    在看官网和学习的过程中,有些不明确子组件和父组件的定义,为了方便后期学习和理解去网站上搜索了一下相关的解释 1.使用的地方是父组件,定义的地方是子组件,虽然他们是同一个组件 2.Vue.compone ...

  10. 使用OpenSSL生成RSA秘钥对并对文件加解密

    生成RSA私钥 openssl genrsa -out rsa.key 1024 生成RSA公钥 openssl rsa -in rsa.key -pubout -out pub.key 创建明文文件 ...