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. hiho1255 Mysterious Antiques in Sackler Museum

    题目链接:http://media.hihocoder.com/contests/icpcbeijing2015/problems.pdf 题目大意:给你四个矩形,判断是否能取其中任意三个组成一个大矩 ...

  2. 【HDU 4343】Interval query(倍增)

    BUPT2017 wintertraining(15) #8D 题意 给你x轴上的N个线段,M次查询,每次问你[l,r]区间里最多有多少个不相交的线段.(0<N, M<=100000) 限 ...

  3. Linux 日志分析脚本

    #### 以下代码,若出现无法使用,请根据底下图片,更改参数.根据 apache 日志格式修改 查看 apache 进程ps aux | grep httpd | grep -v grep | wc ...

  4. Java 枚举 的学习

    在JDK5.0之后,引进了一种与C语言相通的枚举类型. 所谓枚举类型就是指含有一组具有固定值, 并且容量有限的数据集合. 例如,定义一个星期的枚举类型, 从周一到周日是具有固定大小和固定值的集合 pu ...

  5. Android RadioGroup 学习

    Api 参考地址 博文地址 RadioGroup相关属性: //返回该单选按钮组中所选择的单选按钮的标识 ID,如果没有选中的单选按钮则返回 -1. RadioGroup.getCheckedRadi ...

  6. BM算法

    BM算法 用来求解一个数列的递推式. 即给定\(\{x_i\}\)求解一个\(\{a_i\}\),满足\(|a|=m,x_n=\sum_{i=1}^ma_i*x_{n-i}\). 考虑增量法构造. 假 ...

  7. Squid代理服务部署

    构建Squid代理服务器1.配置IP地址 2.编译安装Squid软件[root@localhost ~]# tar -zxvf squid-3.4.6.tar.gz -C /usr/src/[root ...

  8. 解决忘记mysql中的root用户密码问题

    如果忘了数据库中的root密码,无法登陆mysql. 解决步骤: 1. 使用“--skip-grant-tables”启动数据库 ~]#systemctl stop mysql ~]#mysqld_s ...

  9. Miniconda 虚拟环境安装及应用

    首先要下载Miniconda安装包 下载地址  链接:https://pan.baidu.com/s/1rj-9exKBSHnCCxqq7JQSxA      提取码:ab53 下一步 打开下载好的M ...

  10. P2602 [ZJOI2010]数字计数

    https://www.luogu.org/problemnew/show/P2602 数位dp #include <bits/stdc++.h> using namespace std; ...