HDU--6393--Traffic Network in Numazu (树链剖分)

版权声明:本文为原创文章,转载请标明出处。 https://blog.csdn.net/qq_37171272/article/details/81660690

题目链接

思路:n个点n条边必定有一个环,那么在加边的时候判断一下如果当前加的边会构成环,就吧这条边断开,其中一个端点换成n+1,那么就形成了一个n+1个点n条边的树,然后裸的树链剖分,答案取三种情况的最小值就好,具体看代码~

AC代码:

#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;
}

猜你喜欢

转载自blog.csdn.net/qq_37171272/article/details/81660690