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 ...
随机推荐
- 获取hdfs集群信息(fs.defaultFS)
[root@hive-dp-7bd6fd4d55-wctjn hive-1.1.0-cdh5.14.0]# hdfs getconf -confKey fs.default.name19/12/04 ...
- leetcode.字符串.14最长公共前缀-Java
1. 具体题目 编写一个函数来查找字符串数组中的最长公共前缀.如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","fl ...
- leetcode.哈希表.128最长连续序列-Java
1. 具体题目 给定一个未排序的整数数组,找出最长连续序列的长度.要求算法的时间复杂度为 O(n). 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 ...
- touchWX使用 echarts
<button bindtap="init" wx:if="{{!isLoaded}}">加载图表</button> <butto ...
- C语言结构体内存分配详情
#include <stdio.h> int main() { /*************************************************** * * 结构体内存 ...
- 1 新增硬盘挂载home文件夹。 2 修理扇区
一 挂载新硬盘 主机磁盘容量不够大时,想新增一颗新磁盘的时候.并将磁盘全部分割成单一分割槽,且将该分割槽挂载到/home目录,你该怎么做呢? 1 安装硬盘. 2 磁盘分区. 3 格式化磁盘 4 将 ...
- vue 学习一 组件生命周期
先上一张vue组件生命周期的流程图 以上就是一个组件完整的生命周期,而在组件处于每个阶段时又会提供一些周期钩子函数以便我们进行一些逻辑操作,而总体来讲 vue的组件共有8个生命周期钩子 beforeC ...
- 一个简易h5涉及的ps技巧
事实证明,很长时间不做,是会忘掉的呀,的呀,呀,啊~ 1.合并图层 CTRL+E合并多个图层 2.切片 3.导出 文件-------导出------存储为web所用格式-------->> ...
- DIV内容超出固定宽度部分用省略号代替
方法一:CSS控制溢出文本 只针对DIV单行数据展示 /** DIV文本超出宽度部分用...替换,鼠标移上显示全部 **/ .textAuto{overflow:hidden;text-overfl ...
- 依赖背包优化——ural1018,金明的预算方案
经典题了,网上博客一大堆O(nCC)的做法,其实是可以将复杂度降到O(nC)的 参考依赖背包优化(泛化物品的并) 根据背包九讲,求两个泛化物品的和复杂度是O(CC)的,所以依赖背包暴力求解的复杂度是O ...