zoukankan      html  css  js  c++  java
  • hdu6393 /// 树链剖分

    题目大意:

    给定n q

    在n个点n条边的图中

    进行q次操作

    0 k x 为修改第k条边的值为x

    1 x y 为查询x到y的最短路

    https://blog.csdn.net/nka_kun/article/details/81675119

    用其中n-1条边构成一棵树 树链剖分

    多出的那条边记录好 编号s 边的两端su sv 边权sw

    此时两点间最短路为三种情况取小

    树上x到y、树上x到su + 树上y到sv + sw、树上x到sv + 树上y到su + sw

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define INF 0x3f3f3f3f
    #define mem(i,j) memset(i,j,sizeof(i))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define root 1,n,1
    const int N=1e5+5;
    int n,q;
    
    struct QTree {
        struct EDGE { int to,ne; }e[N<<1];
        int head[N], tot;
        void add(int u,int v) {
            e[tot].to=v;
            e[tot].ne=head[u];
            head[u]=tot++;
        }
    
        int fa[N], son[N], dep[N], num[N];
        int top[N], p[N], fp[N], pos;
    
        LL sumT[N<<2];
    
        void init() {
            tot=1; mem(head,0);
            pos=0; mem(son,0);
        }
    
    // --------------------以下是线段树-------------------------
    
        void pushup(int rt) {
            sumT[rt]=sumT[rt<<1]+sumT[rt<<1|1];
        }
        void build(int l,int r,int rt) {
            if(l==r) {
                sumT[rt]=0; return ;
            }
            int m=(l+r)>>1;
            build(lson), build(rson);
            pushup(rt);
        }
        void update(int k,int w,int l,int r,int rt) {
            if(l==r) {
                sumT[rt]=w; return;
            }
            int m=(l+r)>>1;
            if(k<=m) update(k,w,lson);
            else update(k,w,rson);
            pushup(rt);
        }
        LL query(int L,int R,int l,int r,int rt) {
            if(L<=l && r<=R) return sumT[rt];
            int m=(l+r)>>1; LL res=0;
            if(L<=m) res+=query(L,R,lson);
            if(R>m) res+=query(L,R,rson);
            return res;
        }
    
    // --------------------以上是线段树-------------------------
    
    
    
    // --------------------以下是树链剖分-------------------------
    
        void dfs1(int u,int pre,int d) {
            dep[u]=d; fa[u]=pre; num[u]=1;
            for(int i=head[u];i;i=e[i].ne) {
                int v=e[i].to;
                if(v!=fa[u]) {
                    dfs1(v,u,d+1);
                    num[u]+=num[v];
                    if(!son[u] || num[v]>num[son[u]])
                        son[u]=v;
                }
            }
        }
        void dfs2(int u,int sp) {
            top[u]=sp; p[u]=++pos; fp[p[u]]=u;
            if(!son[u]) return;
            dfs2(son[u],sp);
            for(int i=head[u];i;i=e[i].ne) {
                int v=e[i].to;
                if(v!=son[u] && v!=fa[u])
                    dfs2(v,v);
            }
        }
        LL queryPath(int x,int y) {
            LL ans=0;
            int fx=top[x], fy=top[y];
            while(fx!=fy) {
                if(dep[fx]>=dep[fy]) {
                    ans+=query(p[fx],p[x],root);
                    x=fa[fx];
                } else {
                    ans+=query(p[fy],p[y],root);
                    y=fa[fy];
                }
                fx=top[x], fy=top[y];
            }
            if(x==y) return ans;
            if(dep[x]>dep[y]) swap(x,y);
            return ans+query(p[son[x]],p[y],root);
        }
    
    // --------------------以上是树链剖分-------------------------
    
        void initQTree() {
            dfs1(1,0,0);
            dfs2(1,1);
            build(root);
        }
    }T;
    int E[N][3];
    int fa[N];
    int getfa(int x) {
        if(x==fa[x]) return x;
        else return fa[x]=getfa(fa[x]);
    }
    
    int main()
    {
        int t; scanf("%d",&t);
        while(t--) {
            scanf("%d%d",&n,&q);
            T.init();
            int s,su,sv,sw;
            for(int i=1;i<=n;i++) fa[i]=i;
            for(int i=1;i<=n;i++) {
                int u,v,w; scanf("%d%d%d",&u,&v,&w);
                E[i][0]=u, E[i][1]=v, E[i][2]=w;
                int fu=getfa(u), fv=getfa(v);
                if(fu==fv) s=i,su=u,sv=v,sw=w;
                else fa[fu]=fv,T.add(u,v),T.add(v,u);
            }
            T.initQTree();
            for(int i=1;i<=n;i++) {
                if(i==s) continue;
                if(T.dep[E[i][0]]>T.dep[E[i][1]])
                    swap(E[i][0],E[i][1]);
                T.update(T.p[E[i][1]],E[i][2],root);
            }
            while(q--) {
                int op; scanf("%d",&op);
                if(op==0) {
                    int k,w; scanf("%d%d",&k,&w);
                    if(k==s) sw=w;
                    else T.update(T.p[E[k][1]],w,root);
                } else {
                    int x,y; scanf("%d%d",&x,&y);
                    LL ans=sw+T.queryPath(x,su)+T.queryPath(sv,y);
                    ans=min(ans,sw+T.queryPath(x,sv)+T.queryPath(y,su));
                    ans=min(ans,T.queryPath(x,y));
                    printf("%lld
    ",ans);
                }
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    1057 Stack (分块思想)
    1034 Head of a Gang (边不重复 dfs+map)
    1013 Battle Over Cities (dfs 或 并查集)
    1098 Insertion or Heap Sort (堆)
    Oracle中如何进行进制转换(2进制,10进制,16进制)
    ORACLE 36进制和10进制,互相转换函数
    Hive基本命令整理
    Hadoop、Pig、Hive、NOSQL 学习资源收集
    大数据架构师基础:hadoop家族,Cloudera产品系列等各种技术
    常用数据结构及复杂度
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10389238.html
Copyright © 2011-2022 走看看