HDU - 6393 Traffic Network in Numazu(线段树+LCA+树链剖分+并查集)

HDU - 6393 Traffic Network in Numazu(线段树+LCA+树链剖分+并查集)

题目大意:给出一个由n个点和n条边组成的图,每条边都有权值,题目保证图是连通的,然后给出m个询问,每次询问分为两种形式:
0 x y:将第x条边的权值修改为y
1 x y:查询x-y这条路径上的权值和
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m,vis[maxn];
///**树链剖分
int tot,num;
int head[maxn],fa[maxn],deep[maxn],son[maxn],sz[maxn],top[maxn],id[maxn];
int val[maxn];///点权
struct E{int to,next,val;}edge[maxn*2];
struct P{int u,v,val;}e[maxn];
void add_edge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init()
{
    num=tot=0;
    for(int i=1;i<=n+1;i++) head[i]=-1,vis[i]=0;
}
void dfs1(int u,int f,int dep)
{
    fa[u]=f;deep[u]=dep;
    son[u]=0;sz[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(v==f) continue;
        dfs1(v,u,dep+1);
        sz[u]+=sz[v];
        if(sz[v]>sz[son[u]]) son[u]=v;
    }
}
void dfs2(int u,int tp)
{
    id[u]=++num;
    top[u]=tp;
    if(son[u]) dfs2(son[u],tp);
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(v==son[u]||v==fa[u]) continue;
        dfs2(v,v);
    }
}
 
///线段树部分
#define ls rt<<1
#define rs rt<<1|1
#define ll t[rt].l
#define rr t[rt].r
#define LL long long
struct node
{
    int l,r;
    LL val;
}t[maxn*4];
void pushup(int rt)
{
    t[rt].val=t[ls].val+t[rs].val;
}
void build(int rt,int l,int r)
{
    t[rt].l=l;
    t[rt].r=r;
    if(l==r){
        t[rt].val=(LL)val[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(rt);
}
void update(int rt,int pos,int val)
{
    if(ll==rr){
        t[rt].val=(LL)val;
        return ;
    }
    int mid=(ll+rr)>>1;
    if(pos<=mid) update(ls,pos,val);
    else update(rs,pos,val);
    pushup(rt);
}
LL query(int rt,int l,int r)
{
    if(l<=ll&&rr<=r) return t[rt].val;
    int mid=(ll+rr)>>1;
    LL ans=0;
    if(l<=mid) ans+=query(ls,l,r);
    if(r>mid) ans+=query(rs,l,r);
    return ans;
}
 
///
LL solve(int u,int v)
{
    int tp1=top[u],tp2=top[v];
    LL ans=0;
    while(tp1!=tp2){
        if(deep[tp1]<deep[tp2]) swap(u,v),swap(tp1,tp2);
        ans+=query(1,id[tp1],id[u]);
        u=fa[tp1];
        tp1=top[u];
    }
    if(u==v) return ans;
    if(deep[u]>deep[v]) swap(u,v);
    ans+=query(1,id[son[u]],id[v]);
    return ans;
}
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        init();
        int tx,ty=n+1;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].val);
            if(vis[e[i].u]&&vis[e[i].v]){
                tx=e[i].u;
                e[i].u=n+1;
            }
            vis[e[i].u]=vis[e[i].v]=1;
            add_edge(e[i].u,e[i].v);
            add_edge(e[i].v,e[i].u);
        }
        dfs1(1,0,0);
        dfs2(1,1);
        for(int i=1;i<=n;i++){
            if(deep[e[i].u]<deep[e[i].v]) swap(e[i].u,e[i].v);
            val[id[e[i].u]]=e[i].val;
        }
        build(1,1,num);
        int op,u,v;
        while(m--){
            scanf("%d%d%d",&op,&u,&v);
            if(op==0) update(1,id[e[u].u],v);
            else  printf("%lld\n",min(solve(u,v),min(solve(u,tx)+solve(v,ty),solve(u,ty)+solve(v,tx))));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值