http://acm.hdu.edu.cn/showproblem.php?pid=6393

题意

给n个点和n条边的图,有两种操作,一种修改边权,另一种查询u到v的最短路。

分析

n个点和n条边,实际上是一棵树+一个环,如果仅仅是一棵树,那么这题就是树链剖分的模板题了。

对于环来说,可以考虑先把环中一条边提取出来,然后树链剖分,修改时用线段树,单点修改和区间求和。

查询时就考虑三种情况,u走树上到v,从u经过提取出来的边再到v(两种),取最小值。

至于取出环上一条边,用并查集搞搞。

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5+; struct side {
int u,v,w;
int ne;
} s[maxn]; struct edge {
int l,r;
ll v;
} e[maxn<<]; int n,q;
int head[maxn],len;
int val[maxn],hold[maxn],pre[maxn];
int deep[maxn],fa[maxn],ve[maxn],son[maxn],top[maxn],p[maxn],fp[maxn],sz; void add(int u,int v,int w) {
s[len].u = u;
s[len].v = v;
s[len].w = w;
s[len].ne = head[u];
head[u] = len++;
} int find(int x) {
return pre[x] == x?x:pre[x] = find(pre[x]);
} void dfs1(int u,int p,int d) {
deep[u] = d;
fa[u] = p;
ve[u] = ;
son[u] = -;
for(int i = head[u]; i!= -; i = s[i].ne) {
if(s[i].v == p) continue;
val[s[i].v] = s[i].w; //把边权值赋给相连的点
hold[i>>] = s[i].v;//这条边的权值被哪个点掌握着
dfs1(s[i].v,u,d+);
ve[u]+= ve[s[i].v];
if(son[u] == -||ve[s[i].v]> ve[son[u]])
son[u] = s[i].v;
}
return ;
} void dfs2(int u,int sp) {
top[u] = sp;
p[u] = ++sz;
fp[p[u]] = u;
if(son[u] == -) return ;
dfs2(son[u],sp);
for(int i = head[u]; i!= -; i = s[i].ne) {
if(s[i].v == son[u]||s[i].v == fa[u]) continue;
dfs2(s[i].v,s[i].v);
}
return ;
} void build(int i,int l,int r) {
e[i].l = l;
e[i].r = r;
if(l == r) {
e[i].v = val[fp[l]];
return ;
} int mid = (l+r)>>;
build(i<<,l,mid);
build(i<<|,mid+,r);
e[i].v = e[i<<].v+e[i<<|].v;
} void modify(int i,int pos,int v) {
if(pos> e[i].r||pos< e[i].l) return ;
if(e[i].l == e[i].r) {
e[i].v = v;
return ;
}
modify(i<<,pos,v);
modify(i<<|,pos,v);
e[i].v = e[i<<].v+e[i<<|].v;
} ll query(int i,int l,int r) {
if(e[i].r< l||e[i].l> r) return ;
if(e[i].l>= l&&e[i].r<= r) return e[i].v;
return query(i<<,l,r)+query(i<<|,l,r);
} ll demand(int x,int y) {
int fx = top[x];
int fy = top[y];
ll ans = ;
while(fx!= fy) {
if(deep[fx]< deep[fy]) {
swap(fx,fy);
swap(x,y);
}
ans+= query(,p[fx],p[x]);
x = fa[fx];
fx = top[x];
}
if(x == y) return ans;
if(deep[x]> deep[y]) swap(x,y);
ans+= query(,p[son[x]],p[y]);
return ans;
} void init() {
sz = len = ;
mem(head,-);
for(int i = ; i<= n; i++) pre[i] = i;
} int main() {
int t;
cin>>t; while(t--) {
int su,sv,sc,ss;
scanf("%d %d",&n,&q);
init();
for(int i = ; i<= n; i++) {
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
int fx = find(u);
int fy = find(v); if(fx == fy) {
len+= ;
ss = i;
su = u;
sv = v;
sc = w;
continue;
} else
pre[fy] = fx;
add(u,v,w);
add(v,u,w);
} dfs1(,-,);
dfs2(,); build(,,n); while(q--) {
int o,x,y;
scanf("%d %d %d",&o,&x,&y);
if(o == ) {
x--;
if(x == ss) {
sc = y;
continue;
}
modify(,p[hold[x]],y);
} else {
ll ans;
ans = sc+min(demand(x,su)+demand(y,sv),demand(x,sv)+demand(y,su));
ans = min(ans,demand(x,y));
printf("%lld\n",ans);
}
}
}
return ;
}

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

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

    题意:给定一个带权边无向基环树,有两种操作,一种是改变某个边的权值,另一种是询问两点间的最短路径. 可以对环进行缩点,以环为根建立一棵新树,并记录与环相连的所有点和环上的哪个点相连,将路径分为环外和环 ...

  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. HDU 2460 Network(双连通+树链剖分+线段树)

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

  5. HDU 6162 Ch's gift(树链剖分+线段树)

    题意: 已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点u到节点v的最短路径上的节点值在l到r之间的节点值的和. 思路: 用树链剖分将树映射到线段树上,线段树上维护3个值,max,mi ...

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

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

  7. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  8. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  9. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

随机推荐

  1. FAQ常见问题解答---搭建hubot

    1. [root@test160 ~]# npm install -g n npm ERR! Error: CERT_UNTRUSTED 证书不受信任的 解决办法: npm config set st ...

  2. rt-thread之stm32系列BSP制作方法

    @2019-01-24 [小记] bsp制作方法: 官网下载 rt-thread 源码,将路径 bsp/stm32/libraries/templates/ 下的模板文件,Copy至路径 bsp/st ...

  3. A1046. Shortest Distance

    The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed t ...

  4. [luogu3709][大爷的字符串题]

    题目链接 题意 一天做到两道这种题目描述如此神仙的题也是够了.真锻炼语文能力. 题目的意思其实就是,给你一个序列,然后每次询问一个区间.使得尽量按照严格上升的顺序从这个区间内取数.如果当前取得数字小于 ...

  5. 获取url中的参数并以对象的形式展示出来

    速记:获取url中的参数并以对象的形式展示出来 function getUrlData(){ let url=window.location.search;//url中?之后的部分 console.l ...

  6. linux 日常中会用到的命令(持续更新)

    1. grep 比如,我要查看www目录下所有包含   “聊天室”  的文件 grep -rn "聊天室" * 比如我要把  www  目录下所有文件中的    聊天室   替换为 ...

  7. Redis和memcached区别须知

    1.支持的数据类型不同(memcached只支持简单的key-value的数据类型,Redis支持5种数据类型(1.string,2.list,3.set,4.zset,5.hash)) 2.redi ...

  8. Redis在python中的使用

    一 简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted ...

  9. R语言实现两文件对应行列字符替换(解决正负链统一的问题)

    假设存在文件file1.xlsx,其内容如下: 存在文件file2.xlsx,其内容如下: 现在我想从第七列开始,将file2所有的字符替换成file1一样的,即第七.八.九.十列不需要改变,因为fi ...

  10. free(): invalid next size (fast): 0x000000xxx

    记录一次错误,一开始看到这个错误,第一反应是不是释放了两次,后来检测绝对没有,然后又检查了下是不是new/malloc和delete/free没配对, 发现也不是,最后是发现new[x]中x是0的缘故 ...