zoukankan      html  css  js  c++  java
  • hdu 6393 Traffic Network in Numazu (树链剖分+线段树 基环树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6393

    思路:n个点,n条边,也就是基环树。。因为只有一个环,我们可以把这个环断开,建一个新的点n+1与之相连,然后就按照树链剖分求边权的方法分类讨论下,过不过这条被分开的边,一共有三种情况取值最小的。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define ll long long
    #define mid int m = (l + r) >> 1
    const int M = 1e5+10;
    int cnt,cnt1,head[M],fa[M],dep[M],son[M],siz[M],top[M],tid[M],n,q,vis[M];
    ll val[M];
    ll sum[M<<2];
    struct node{
        int to,next;
        ll val;
    }e[M];
    
    struct node1{
        int u,v;
        ll val;
    }a[M];
    void add(int u,int v){
        e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
    }
    
    void dfs1(int u,int faz,int deep){
        dep[u] = deep;
        fa[u] = faz;
        siz[u] = 1;
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v == fa[u]) continue;
            dfs1(v,u,deep+1);
            siz[u] += siz[v];
            if(siz[v] > siz[son[u]]||son[u]==-1)
                son[u] = v;
        }
    }
    
    void dfs2(int u,int t){
        top[u] = t;
        tid[u] = ++cnt1;
        if(son[u] == -1) return ;
        dfs2(son[u],t);
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v != fa[u]&&v != son[u])
                dfs2(v,v);
    
        }
    }
    
    void pushup(int rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void build(int l,int r,int rt){
         if(l == r){
            sum[rt] = val[l];
            return ;
         }
         mid;
         build(lson); build(rson);
         pushup(rt);
    }
    
    void update(int p,ll c,int l,int r,int rt){
        if(l == r){
            sum[rt] = c;
            return ;
        }
        mid;
        if(p <= m) update(p,c,lson);
        else update(p,c,rson);
        pushup(rt);
    }
    
    ll query(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r)  return sum[rt];
        mid;
        ll ret = 0;
        if(L <= m) ret += query(L,R,lson);
        if(R > m) ret += query(L,R,rson);
        return ret;
    }
    
    /*void ct(int l,int r,int rt){
        if(l == r){
            cout<<sum[rt]<<" ";
            return ;
        }
        mid;
        ct(lson); ct(rson);
    }*/
    
    ll solve(int x,int y){
        int fx = top[x],fy = top[y];
        ll ans = 0;
        while(fx != fy){
            if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y);
            if(fx == 1) ans += query(tid[fx]+1,tid[x],1,n+1,1);
            else ans += query(tid[fx],tid[x],1,n+1,1);
           // cout<<x<<" "<<fx<<" "<<ans<<endl;
            x = fa[fx]; fx = top[x];
        }
        if(x == y) return ans;
        if(dep[x] > dep[y]) swap(x,y);
        ans += query(tid[son[x]],tid[y],1,n+1,1);
        return ans;
    }
    
    void init(){
        cnt = cnt1 = 0;
        memset(son,-1,sizeof(son));
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&q);
            init();
            int tx,ty = n+1;
            for(int i = 1;i <= n;i ++){
                scanf("%d%d%lld",&a[i].u,&a[i].v,&a[i].val);
                if(vis[a[i].u]&&vis[a[i].v]){
                    tx = a[i].u;
                    a[i].u = n+1;
                }
                vis[a[i].u] = vis[a[i].v] = 1;
                add(a[i].u,a[i].v);
                add(a[i].v,a[i].u);
            }
           // cout<<"jsjd: "<<tx<<" "<<ty<<endl;
            dfs1(1,0,1);
            dfs2(1,1);
            for(int i = 1;i <= n;i ++){
                if(dep[a[i].u] < dep[a[i].v])swap(a[i].u,a[i].v);
                val[tid[a[i].u]] = a[i].val;
            }
            build(1,n+1,1);
          //  ct(1,n+1,1);cout<<endl;
            while(q--){
                int op,x,y;
                scanf("%d%d%d",&op,&x,&y);
                if(op == 0) update(tid[a[x].u],y,1,n+1,1);
                else{
                    ll num = solve(x,tx)+solve(y,ty);
                    ll num1 = solve(x,ty)+solve(y,tx);
                    //cout<<"num: "<<num<<"num1 : "<<num1<<"solve "<<solve(x,y)<<endl;
                    printf("%lld
    ",min(solve(x,y),min(num,num1)));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    python之Socket网络编程
    python_异常处理
    python_面向对象编程
    Vue-cli3与springboot项目整合打包
    命令打开java控制面板
    后端记录用户登录失败次数
    跨域问题解决办法
    vue-i18n多语言文件归类的两种方法
    svn全局设置过滤文件没有作用的解决办法
    vue数据变化后页面刷新
  • 原文地址:https://www.cnblogs.com/kls123/p/9703786.html
Copyright © 2011-2022 走看看