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

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

 #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. 自定义 filter simple_tag inclusion_tag 总结

    在已经注册的app下创建templatetags的python包 在包内创建py文件 my_tags.py 在py文件中写代码: from django import template registe ...

  2. staticmethod自己定制

    class StaticMethod: def __init__(self,func): self.func=func def __get__(self, instance, owner): #类来调 ...

  3. __setattr__,__getattr__,__delattr__

    class Foo: x = 1 def __init__(self,y): self.y = y def __getattr__(self,item): print("---->fr ...

  4. Nginx的root和alias区别

    1.root 下面举例说明: location /i/ { root /data/w3; } 请求 http://foofish.net/i/top.gif 这个地址时,那么在服务器里面对应的真正的资 ...

  5. Android selector一些坑

    最近给textview添加seletor时,发现textcolor和background要分开成两个selector.并且,textcolor的要再res路径下建color路径,然后在color下面建 ...

  6. java第一次实验总结&第三周总结

    Java第一次实验报告,java开发环境与简单的Java程序 一.实验目的 1.熟悉JDK开发环境 2.熟练掌握结构化程序设计方法 二.实验内容 打印输出所有的"水仙花数",所谓& ...

  7. [转帖]Oracle 数据库官方不支持VMWare

    Oracle 数据库官方不支持VMWare [日期:2014-05-13] 来源:Linux社区  作者:myhuaer [字体:大 中 小]   https://www.linuxidc.com/L ...

  8. 什么是云服务器ECS

    云服务器(Elastic Compute Service,简称ECS)是阿里云提供的性能卓越.稳定可靠.弹性扩展的IaaS(Infrastructure as a Service)级别云计算服务.云服 ...

  9. 卸载mysql后再安装提示The service already exists!问题解决方法

    卸载mysql后再安装输入mysqld --install 回车后提示The service already exists! 原因:卸载的时候没有卸载干净 方法: 一.重新以管理员身份打开cmd 二. ...

  10. 【模板】SPFA(不完全详解)

    一种最短路求法(个人觉得比DIJKSTRA好用) 用于有向图. 大概思路:从根节点开始,枚举每一个点,同时更新他们所联通的点的最短路径,如果路径被更新,则把这个点入队,一直重复这个操作直到队伍为空为止 ...