zoukankan      html  css  js  c++  java
  • HDU-6393 Traffic Network in Numazu

    题意:给你一个n边n点的无向连通图,两个操作,操作一改变某个边的权值,操作二查询某两个点之间的路径长度。

    题解:随便删掉环上一条边搞一棵树出来,因为两点间距离是两点各自到根的距离之和减去2*lca两点到根的距离。

               所以修改操作就变为维护点到根这条链上的权值,差分一下 采用树状数组维护。

               查询的时候就是用删掉那条边和不用两种情况,比较一下大小就好了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+777;
    int E[N],dfn[N],F[N],L[N],R[N],deep[N],inv[N],f[N][20],to[N<<1],w[N<<1],nxt[N<<1],H[N];
    int W,X,Y,n,T,m,Q,x,y,z,tar,tot,cnt;
    long long C[N];
    void add(int u,int v,int z){
        to[tot]=v,w[tot]=z,nxt[tot]=H[u],H[u]=tot++;
    }
    void dfs(int u,int fa,int deepth){
        dfn[u]=L[u]=++cnt;
        deep[u]=deepth;
        inv[cnt]=u;
        for(int i=H[u];~i;i=nxt[i]){
            int v=to[i];
            if(v==fa) continue;
            if(dfn[v]) {
                tar=(i>>1)+1;
                W=w[i];
                X=u;
                Y=v;
                continue;
            }
            f[v][0]=u;
            F[v]=w[i];
            E[(i>>1)+1]=v;
            dfs(v,u,deepth+1);
        }
        R[u]=cnt;
    }
    void modify(int u,int v){
        for(;u<=n;u+=u&(-u)) C[u]+=v;
    }
    long long sum(int u){
        long long ans=0;
        for(;u;u-=u&(-u)) ans+=C[u];
        return ans;
    }
    void work(){
        for(int i=1;i<20;++i) for(int j=1;j<=n;++j) f[j][i]=f[f[j][i-1]][i-1];
    }
    int lca(int x,int y){
        if(deep[x]<deep[y]) swap(x,y);
        int dt=deep[x]-deep[y];
        for(int i=0;i<20;++i) if(dt&(1<<i)) x=f[x][i];
        if(x==y) return x;
        for(int i=19;i>=0;--i) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    long long dist(int x,int y){
        return sum(dfn[x])+sum(dfn[y])-2LL*(sum(dfn[lca(x,y)]));
    }
    int main(){
        for(scanf("%d",&T);T--;){
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;++i) H[i]=-1,dfn[i]=C[i]=0;
            tot=cnt=0;
            for(int i=1;i<=n;++i){
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);
                add(y,x,z);
            } 
            dfs(1,0,0);
            work();
            for(int i=1;i<=n;++i) {
                modify(L[inv[i]],F[inv[i]]);
                modify(R[inv[i]]+1,-F[inv[i]]);
            }
            while(m--){
                scanf("%d%d%d",&x,&y,&z);
                if(x==0) {
                    if(tar==y) W=z;
                    else {
                        int i=E[y];
                        modify(L[i],z-F[i]);
                        modify(R[i]+1,-z+F[i]);
                        F[i]=z;
                    }
                }
                else {
                    long long ans=dist(y,z);
                    ans=min(ans,dist(y,X)+dist(z,Y)+W);
                    ans=min(ans,dist(z,X)+dist(y,Y)+W);
                    printf("%lld
    ",ans);
                }
            }
        }
    }
  • 相关阅读:
    Javascript语言精粹之String常用方法分析
    Javascript语言精粹之Array常用方法分析
    Javascript语言精粹之正则表达式知识整理
    深入浅出KnockoutJS
    用KnockoutJS实现ToDoMVC代码分析
    用JavaScript实现网页动态水印
    LINQ to JavaScript 源码分析
    《Javascript高级程序设计》读书笔记之bind函数详解
    《Javascript高级程序设计》读书笔记之闭包
    转载-MySQL 加锁处理分析
  • 原文地址:https://www.cnblogs.com/mfys/p/9472024.html
Copyright © 2011-2022 走看看