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. codeforces1096G Lucky Tickets

    题目链接:https://codeforces.com/problemset/problem/1096/G 大意:给出\(k\)个数码\(d_1,d_2,\cdots,d_k\),构造一个由这\(k\ ...

  2. 【BZOJ4042】【CERC2014】parades 状压DP

    题目大意 给你一棵\(n\)个点的树和\(m\)条路径要求你找出最多的路径,使得这些路径不共边.特别的,每个点的度数\(\leq 10\). \(n\leq 1000,m\leq \frac{n(n- ...

  3. CODEFORCES掉RATING记 #3

    比赛:Codeforces Round #426 (Div. 2) 时间:2017.7.30晚 开场先看AB A:给你两个方向,和旋转次数(每次旋转90度),问你旋转方向是什么 B:给你一个字符串,问 ...

  4. 将xml文件由格式化变为压缩字符串

    标签:去除xml文件的空格 有些时候解析xml文件,要求读取的字符串必须是压缩后的xml文件,不能有多余的空格.考虑到在<>标签内包含空格和大于号的情况,写了以下的转换方式. 传入的是压缩 ...

  5. MT【307】周期数列

    (2017浙江省数学竞赛) 设数列$\{a_n\}$满足:$|a_{n+1}-2a_n|=2,|a_n|\le2,n\in N^+$证明:如果$a_1$为有理数,则从某项后$\{a_n\}$为周期数列 ...

  6. MT【169】拉格朗日配方

    已知$x^2+y^2+z^2=1$求$3xy-3yz+2z^2$的最大值______ 答案:$3$ 提示:$3(x^2+y^2+z^2)-(3xy-3yz+2z^2)=3\left(y+\dfrac{ ...

  7. 牛客小白月赛6C-桃花(DFS/BFS求树的直径)

    链接:https://www.nowcoder.com/acm/contest/136/C 来源:牛客网 桃花 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言 ...

  8. map映照容器

    //map映照容器是由一个键值和一个映照数据组成的,键值与映照数据之间具有一一映照的关系 //map映照容器的键值不允许重复 ,比较函数值对元素 //的键值进行比较,元素的各项数据可通过键值检索出来 ...

  9. 用Python3、NetCore、Shell分别开发一个Ubuntu版的定时提醒(附NetCore跨平台两种发布方式)

    汇总系列:https://www.cnblogs.com/dunitian/p/4822808.html#ai Python3 与 C# 基础语法对比:https://www.cnblogs.com/ ...

  10. nodejs的某些api~(五) HTTP模块

    HTTP的模块是nodejs最重要的模块(应该是),最近在看HTTP权威指南,重新过了一遍http协议和web客户端.再来看这个http. HTTP构建于TCP之上,属于应用层协议,继承自tcp服务器 ...