题目传送门

题意:给出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. ThreeJS模型展示为黑色,模型出不来

    选取gltf格式时,出现模型为黑色,模型出不来 原因: 我们设计部可能是用maya或者3dmax去做:在模型导出时,没有gltf格式:如果maya或者3dmax导出obj然后导进blender,再导出 ...

  2. 5、如何快速找到多个字典中的公共键(key) 6 如何让字典保持有序 7 如何实现用户的历史记录功能(最多n条)

    5.如何快速找到多个字典中的公共键(key) from random import randint,sample #随机取数 # a = sample("ABCDEF",randi ...

  3. java oop第10章_JDBC03(MVC分层模式)

    引言:在进行程序开发的时候,为了更加利于程序的管理我们引入了新的开发模式MVC分层模式,即按功能将程序代码分别分为M(Model模型).V(View视图).C(Controller控制器)三个组成部分 ...

  4. ARM 寄存器 和 工作模式了解

    一. ARM 工作模式 1.   ARM7,ARM9,ARM11,处理器有 7 种工作模式:Cortex-A 多了一个监视模式(Monitor) 2.  用户模式:非特权模式,大部分任务执行在这种模式 ...

  5. elementUI+JS实现全选与反选

    在实际项目开发过程中,遇到的需求,需要实现全选以及取消全选等功能,主要使用ElementUI + JS来实现,具体代码如下: <!DOCTYPE html> <html lang=& ...

  6. 导出Excel(终极版)

    /** * 导出excel 案例 */ public void exportExcel(){ long beginTime = System.currentTimeMillis(); HttpServ ...

  7. thinkphp 日志驱动

    日志驱动默认的命名空间位于Think\Log\Driver,驱动类需要实现的接口方法包括: 方法 说明 架构方法 __construct($config=array()) 写入方法 write($lo ...

  8. bzoj 2257 (JSOI 2009) 瓶子与燃料

    Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了. 有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子来换.jyy 的飞船上共有 N个瓶子(1<=N& ...

  9. NOIp2018集训test-9-17(am)

    这是一套去年在长沙考过的题,但是我当时就没理清楚+没写题解(我以前很多博客都写得跟shi一样,完全没有意义,看到就想打当时的我),所以又考得稀烂. T1.star way to heaven 容易想到 ...

  10. NX二次开发-UFUN工程图表格注释获取某一行的tag函数UF_TABNOT_ask_nth_row

    NX9+VS2012 #include <uf.h> #include <uf_tabnot.h> #include <NXOpen/Part.hxx> #incl ...