题目传送门

题意:给出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 树链剖分的更多相关文章

  1. HDU-6393 Traffic Network in Numazu

    题意:给你一个n边n点的无向连通图,两个操作,操作一改变某个边的权值,操作二查询某两个点之间的路径长度. 题解:随便删掉环上一条边搞一棵树出来,因为两点间距离是两点各自到根的距离之和减去2*lca两点 ...

  2. HDU - 6393 Traffic Network in Numazu(树链剖分+基环树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6393 题意 给n个点和n条边的图,有两种操作,一种修改边权,另一种查询u到v的最短路. 分析 n个点和n条边,实 ...

  3. hdu 6393 Traffic Network in Numazu (树链剖分+线段树 基环树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6393 思路:n个点,n条边,也就是基环树..因为只有一个环,我们可以把这个环断开,建一个新的点n+1与之相 ...

  4. BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 870  Solved: 299[Submit] ...

  5. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  6. HDU 2460 Network(双连通+树链剖分+线段树)

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

  7. 【BZOJ1146】【树链剖分+平衡树】网络管理Network

    Description M 公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 信网络.该网络的结构由N个 ...

  8. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

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

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

随机推荐

  1. 注解@Override

    Android的开发者对@Override肯定是非常熟悉,不管是自己的代码中还是书上都会出现,但是他是什么意思呢?如下: @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: ...

  2. 2014 mathtype分块列向量输入 PPT动画制作

    1.mathtype分块列向量的输入 http://zhidao.baidu.com/link?url=pV7TazWe-Ld5qgxNcJCQdRaA8ILEgmXRP211F5U0Cst0xNfU ...

  3. 深度探索C++对象模型读书笔记-第六章执行期语意学

    在函数中,编译器会帮助将析构函数(Destructor) 安插在相应的位置.对于函数中的局部对象,会将析构函数安插在对象的每一个离开点. 例如: 1: void Function(int a) { 2 ...

  4. 笔记33 Spring MVC的高级技术——Spring MVC配置的替代方案

    一.自定义DispatcherServlet配置  AbstractAnnotationConfigDispatcherServletInitializer所完成 的事情其实比看上去要多.在Spitt ...

  5. 基本TCP Sockets编程

    一.socket 函数 #include <sys/socket.h> int socket (int family, int type, int protocol); Returns: ...

  6. web storem破解

    话不多说 直接跳地址 http://idea.lanyus.com/ 再加个附带汉化包,使用方法已经放在压缩包里面 网盘链接: https://pan.baidu.com/s/1aEA6SSbDuRg ...

  7. EF批量添加数据之修改SQL Server执行上限

    asp.net core 项目 打开Startup.cs services.AddDbContext<MyContext>( options => { options.UseSqlS ...

  8. Go Hello World 实例

    ## Go Hello World 实例 package main import "fmt" func main() { /* This is my first sample pr ...

  9. 阿里云HBase推出全新X-Pack服务 定义HBase云服务新标准

    2018年12月13日,第八届中国云计算标准和应用大会在京召开,会上阿里云HBase宣布推出全新X-Pack服务,支持SQL.时序.时空.图.全文检索能力.复杂分析,从处理到分析全栈式数据库,客户开箱 ...

  10. poi之Excel上传

    poi之Excel上传 @RequestMapping(value = "/import", method = RequestMethod.POST) public String ...