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

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

 #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. go中的数据结构-字典map

    1. map的使用 golang中的map是一种数据类型,将键与值绑定到一起,底层是用哈希表实现的,可以快速的通过键找到对应的值. 类型表示:map[keyType][valueType] key一定 ...

  2. JavaScript 基础入门11 - 运动框架的封装

    目录 JavaScript 运动原理 运动基础 简单运动的封装 淡入淡出 不同属性的设置 多属性值同时运动 运动回调,链式运动 缓冲运动 加入缓冲的运动框架 案例1 多图片展开收缩 运动的留言本 Ja ...

  3. 《Linux命令行大全》 笔记记录

    1.Shell是什么 2.(文件目录)导航 3.Linux系统 4.操作文件和目录 5.命令的使用 6.重定向 7.透过shell看世界 扩展 引用 8.高级键盘技巧 9.权限 10.进程 11.环境 ...

  4. Pytorch1.0深度学习:损失函数、优化器、常见激活函数、批归一化详解

    不用相当的独立功夫,不论在哪个严重的问题上都不能找出真理:谁怕用功夫,谁就无法找到真理. —— 列宁 本文主要介绍损失函数.优化器.反向传播.链式求导法则.激活函数.批归一化. 1 经典损失函数 1. ...

  5. python3.6调用c语言动态编译文件 c语言编译可执行文件和动态编译等

    1.c的代码 dfunc.c #include<stdio.h> int dgfunc(int n) { ){ ; }else{ )+dgfunc(n-); } } 2.动态编译 cmd ...

  6. springboot 打包问题 项目依赖三方jar ,之前的同事是直接丢到项目lib下 ,今天使用springbioot打包的时候,找不到这个jar

    试了很多种方法 最后还是老老实实按照maven 那种格式把三方jar(或者很难下载下来的那种jar) 打包成仓库哪种格式 mvn install:install-file -Dfile=C:\User ...

  7. 与高精死杠的几天——记两道简单的高精dp

    (同样也是noip往年的题 1​.矩阵取数游戏 题目链接[Luogu P1005 矩阵取数游戏] \(\mathcal{SOLUTION}:\) 通过对题目条件的分析,我们可以发现,每一行取数对答案的 ...

  8. Django基础之模型层(下)

    聚合查询 关键字:aggregate from django.db.models import Max,Min,Sum,Count,Avg 统计所有书的平均价格 models.Book.objects ...

  9. 基于CentOS系统部署EPICS环境

    1.虚拟机安装CentOS系统2.打开终端,以root账户登录3.进入/usr/local目录下,新建文件夹epics,并进入该文件夹4.在/usr/local/epics目录下,执行wget htt ...

  10. LVS、Nginx及HAProxy

    本文转载自 linkedkeeper.com   当前大多数的互联网系统都使用了服务器集群技术,集群是将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是 Web 应用服务器集群, ...