题目传送门

题意:给出n个点n条边的无向带权图,再给出两种操作,操作1是将第x条边的边权修改为y,操作2是询问点x到点y的最短路径。

思路:如果是n个点n-1条边,题目就变成了树,修改边权和询问最短路径都可以在树链剖分上直接操作,而添加了一条边后,就在树上形成了一个环。

读入的时候,用并查集判断哪条边是构成那个环的边(我们把这幅图想象成一棵树加上一条边),记录这条边。

    对于修改操作,对于树上的边,用树链剖分修改,对于特殊的边,直接修改。

    对于查询操作,只需要查询两个点在树上的路径,和两个点通过这条边的路径(这种方法有两个值)哪个最小就可以了。

#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=1e5+;
int n,q,head[maxn],tot,u,v,fa[maxn],sc,me[maxn],size[maxn],l[maxn],r[maxn],fin[maxn],son[maxn];
int dep[maxn],top[maxn],hold[maxn];
ll sum[maxn<<];
ll w,val[maxn];
struct edge{
int u,v,id;
ll w;
}a[maxn];
vector<edge >ve[maxn];
void init(){
tot=;
for(int i=;i<=n;i++){
me[i]=i;
}
for(int i=;i<=n;i++){
ve[i].clear();
}
}
int find(int x){
return x==me[x]?x:me[x]=find(me[x]);
}
void build(int o,int ql,int qr){
if(ql==qr){ sum[o]=val[fin[ql]];
// printf("ql:%d qr:%d sum[o]:%d fin[ql]:%d\n",ql,qr,sum[o],fin[ql]);
return;
}
int mid=(ql+qr)>>;
build(o<<,ql,mid);
build(o<<|,mid+,qr);
sum[o]=sum[o<<]+sum[o<<|];
}
void update(int o,int ql,int qr,int p,int v){
if(ql==qr){
sum[o]=v;
return;
}
int mid=(ql+qr)>>;
if(p<=mid)update(o<<,ql,mid,p,v);
else update(o<<|,mid+,qr,p,v);
sum[o]=sum[o<<]+sum[o<<|];
}
ll query(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return sum[o];
int mid=(l+r)>>;
ll res=;
if(ql<=mid)res+=query(o<<,l,mid,ql,qr);
if(qr>mid)res+=query(o<<|,mid+,r,ql,qr);
return res;
}
inline ll get(int x)
{
ll ret = ;
while(top[x]!=)
{
// printf("top[x]:%d\n",top[x]);
ret+=query(,,n,l[top[x]],l[x]);
x=fa[top[x]];
}
ret+=query(,,n,,l[x]);
return ret;
}
int lca(int x,int y){
while(top[x]!=top[y])
{
if(dep[top[x]]>=dep[top[y]])x=fa[top[x]];
else y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
inline void dfs_1(int x,int pre)
{
// printf("x:%d pre:%d\n",x,pre);
fa[x] = pre;
son[x] = -;
size[x] = ;
dep[x] = dep[pre]+;
int si=ve[x].size();
for(int i = ; i < si; i++){
int v=ve[x][i].v; if( v!= pre)
{
val[v]=ve[x][i].w;
hold[ve[x][i].id]=v;
dfs_1(v,x);
size[x] += size[v];
if(son[x]==- || size[v]>size[son[x]]) son[x] = v;
}
}
}
inline void dfs_2(int x,int root)
{
top[x] = root;
l[x] = ++tot;
fin[l[x]] = x;
if(son[x] != -)
dfs_2(son[x],root);
int si=ve[x].size();
for(int i = ; i < si; i++){
int v=ve[x][i].v;
if(v != fa[x] && v != son[x])
dfs_2(v,v);
}
r[x]=tot;
}
int main(){
int T;
cin>>T;
while(T--){
scanf("%d%d",&n,&q);
init();
for(int i=;i<=n;i++){
scanf("%d%d%lld",&a[i].u,&a[i].v,&a[i].w);
a[i].id=i;
int fu=find(a[i].u),fv=find(a[i].v);
// printf("u:%d v:%d fu:%d fv:%d\n",u,v,fu,fv);
if(fu!=fv){
me[fu]=fv;
ve[a[i].u].push_back({a[i].u,a[i].v,i,a[i].w});
ve[a[i].v].push_back({a[i].v,a[i].u,i,a[i].w});
}else{
sc=i;
}
} dfs_1(,);
// printf("debug\n");
dfs_2(,);
build(,,n);
int op,x,y;
while(q--){
scanf("%d%d%d",&op,&x,&y);
if(op==){
if(x==sc){
a[sc].w=y;
}else{
update(,,n,l[hold[x]],y);
}
}else{
int lc=lca(x,y);
ll ans=get(x)+get(y)-*get(lc);
ll res1=get(x)+get(a[sc].u)-*(get(lca(x,a[sc].u)))+get(y)+get(a[sc].v)-*(get(lca(y,a[sc].v)));
ll res2=get(x)+get(a[sc].v)-*(get(lca(x,a[sc].v)))+get(y)+get(a[sc].u)-*(get(lca(y,a[sc].u)));
printf("%lld\n",min(ans,a[sc].w+min(res1,res2)));
}
}
}
}

hdu6393 Traffic Network in Numazu 树链剖分的更多相关文章

  1. HDU-6393 Traffic Network in Numazu

    题意:给你一个n边n点的无向连通图,两个操作,操作一改变某个边的权值,操作二查询某两个点之间的路径长度. 题解:随便删掉环上一条边搞一棵树出来,因为两点间距离是两点各自到根的距离之和减去2*lca两点 ...

  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 (树链剖分+线段树 基环树)

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

  4. BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 870  Solved: 299[Submit] ...

  5. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  6. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  7. 【BZOJ1146】【树链剖分+平衡树】网络管理Network

    Description M 公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 信网络.该网络的结构由N个 ...

  8. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

  9. [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)

    题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...

随机推荐

  1. 服务器搭建node环境

    最近由于工作原因开始学习服务器的搭建和环境配置.记录一下我在服务器搭建node环境的步骤.中间踩了很多坑. 首先,确定自己的服务器可以连接到外网,如果连接不上的话,会出现ETIMEOUT的报错,但这只 ...

  2. Linux SSH证书登陆

    创建证书 ssh-keygen -t rsa -b 4096 -C "your_email@example.com" 证书导入以后,执行 eval "$(ssh-agen ...

  3. java-day25

    . 标签学习:         1. 文件标签:构成html最基本的标签             * html:html文档的根标签             * head:头标签.用于指定html文档 ...

  4. SVM-SVR

    高频率的接触到了SVM模型,而且还有使用SVM模型做回归的情况,即SVR.另外考虑到自己从第一次知道这个模型到现在也差不多两年时间了,从最开始的腾云驾雾到现在有了一点直观的认识,花费了不少时间.因此在 ...

  5. vue on emit 父子之间传值应用详细代码

    大概很多人都知道用这个,网上教程也一大堆,但我想说的是一定要手动敲一遍,敲一遍,敲一遍,重要的事情说三遍. 大概有些人也不知道它该何时用on,或者emit 的吧? 先说两个我项目中用到的场景吧: 项目 ...

  6. python项目部署

    WSGI简介 Web框架和Wen服务器之间需要进行通信,如果在设计时它们之间无法相互匹配,那么对框架的选择就会限制对Web服务器的选择,这显然是不合理的.这时候需要设计一套双方都遵守的接口.WSGI是 ...

  7. 21-7-数组相关api

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Box-Cox变换

    简介 编辑 Box-Cox变换的一般形式为: 式中    为经Box-Cox变换后得到的新变量,    为原始连续因变量,    为变换参数.以上变换要求原始变量    取值为正,若取值为负时,可先对 ...

  9. 高危预警|RDP漏洞或引发大规模蠕虫爆发,用户可用阿里云免费检测服务自检,建议尽快修复

    2019年9月6日,阿里云应急响应中心监测到Metasploit-framework官方在GitHub空间公开了针对Windows远程桌面服务远程命令执行漏洞(CVE-2019-0708)的利用代码. ...

  10. thinkphp cookie支持

    系统内置了一个cookie函数用于支持和简化Cookie的相关操作,该函数可以完成Cookie的设置.获取.删除操作. Cookie设置 cookie('name','value'); //设置coo ...