hdu6393 Traffic Network in Numazu 树链剖分
题意:给出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 树链剖分的更多相关文章
- HDU-6393 Traffic Network in Numazu
题意:给你一个n边n点的无向连通图,两个操作,操作一改变某个边的权值,操作二查询某两个点之间的路径长度. 题解:随便删掉环上一条边搞一棵树出来,因为两点间距离是两点各自到根的距离之和减去2*lca两点 ...
- HDU - 6393 Traffic Network in Numazu(树链剖分+基环树)
http://acm.hdu.edu.cn/showproblem.php?pid=6393 题意 给n个点和n条边的图,有两种操作,一种修改边权,另一种查询u到v的最短路. 分析 n个点和n条边,实 ...
- hdu 6393 Traffic Network in Numazu (树链剖分+线段树 基环树)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6393 思路:n个点,n条边,也就是基环树..因为只有一个环,我们可以把这个环断开,建一个新的点n+1与之相 ...
- BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 870 Solved: 299[Submit] ...
- BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )
树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- 【BZOJ1146】【树链剖分+平衡树】网络管理Network
Description M 公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 信网络.该网络的结构由N个 ...
- BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
随机推荐
- 【Java多线程系列五】列表类
一些列表类及其特性 类 线程安全 Iterator 特性 说明 Vector 是 fail-fast 内部方法用synchronized修饰,因此执行效率较低 1. 线程安全的列表类并不意味着调用它 ...
- 【Java多线程系列随笔一】浅析 Java Thread.join()
一.在研究join的用法之前,先明确两件事情. 1.join方法定义在Thread类中,则调用者必须是一个线程, 例如: Thread t = new CustomThread(); //这里一般是自 ...
- Maven Optional & Exclusions使用区别
Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反. Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖 ...
- 反射与类加载之反射基本概念与Class(一)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从以下几个内容来阐述反射与类加载: [三种获取Class对象的方式] [ ...
- springbot项目中使用继承
package com.example.demo.controller; import com.sun.org.apache.bcel.internal.generic.NEW; import org ...
- pytest的断言、跳过、运行的按需要处理
def test_one(): assert 1==1 assert 1!=2 assert {'name':'linda','age':19}=={'name':'linda','age':190} ...
- 实现简单的PHP接口,以及使用js/jquery ajax技术调用此接口
主要介绍下如何编写简单的php接口,以及使用js/jquery的ajax技术调用此接口. Php接口文件(check.php): <?php $jsonp_supporter = $_GET[‘ ...
- C# ASCII码和英文字母相互转换和ASCII码对照表
1.字母转换成ASCII码 string str = "hello"; ]; array = System.Text.Encoding.ASCII.GetBytes(str); / ...
- Atcoder arc092
E-Both Sides Merger 给你一个序列,支持两种操作,直到序列中只有一个数时停下来,使得剩下数最大,并输出选数方案. 操作1:扔掉一个最前端或最后端的元素.操作2:选取一个不在边界上的元 ...
- leetcood学习笔记-110-平衡二叉树
---恢复内容开始--- 题目描述: 方法一: class Solution(object): def isBalanced(self, root): """ :type ...