• HDU


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

    题意

    给n个点和n条边的图,有两种操作,一种修改边权,另一种查询u到v的最短路。

    分析

    n个点和n条边,实际上是一棵树+一个环,如果仅仅是一棵树,那么这题就是树链剖分的模板题了。

    对于环来说,可以考虑先把环中一条边提取出来,然后树链剖分,修改时用线段树,单点修改和区间求和。

    查询时就考虑三种情况,u走树上到v,从u经过提取出来的边再到v(两种),取最小值。

    至于取出环上一条边,用并查集搞搞。

    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const int maxn = 2e5+5;
    
    struct side {
        int u,v,w;
        int ne;
    } s[maxn];
    
    struct edge {
        int l,r;
        ll v;
    } e[maxn<<2];
    
    int n,q;
    int head[maxn],len;
    int val[maxn],hold[maxn],pre[maxn];
    int deep[maxn],fa[maxn],ve[maxn],son[maxn],top[maxn],p[maxn],fp[maxn],sz;
    
    void add(int u,int v,int w) {
        s[len].u = u;
        s[len].v = v;
        s[len].w = w;
        s[len].ne = head[u];
        head[u] = len++;
    }
    
    int find(int x) {
        return pre[x] == x?x:pre[x] = find(pre[x]);
    }
    
    void dfs1(int u,int p,int d) {
        deep[u] = d;
        fa[u] = p;
        ve[u] = 1;
        son[u] = -1;
        for(int i = head[u]; i!= -1; i = s[i].ne) {
            if(s[i].v == p) continue;
            val[s[i].v] = s[i].w; //把边权值赋给相连的点
            hold[i>>1] = s[i].v;//这条边的权值被哪个点掌握着
            dfs1(s[i].v,u,d+1);
            ve[u]+= ve[s[i].v];
            if(son[u] == -1||ve[s[i].v]> ve[son[u]])
                son[u] = s[i].v;
        }
        return ;
    }
    
    void dfs2(int u,int sp) {
        top[u] = sp;
        p[u] = ++sz;
        fp[p[u]] = u;
        if(son[u] == -1) return ;
        dfs2(son[u],sp);
        for(int i = head[u]; i!= -1; i = s[i].ne) {
            if(s[i].v == son[u]||s[i].v == fa[u]) continue;
            dfs2(s[i].v,s[i].v);
        }
        return ;
    }
    
    void build(int i,int l,int r) {
        e[i].l = l;
        e[i].r = r;
        if(l == r) {
            e[i].v = val[fp[l]];
            return ;
        }
    
        int mid = (l+r)>>1;
        build(i<<1,l,mid);
        build(i<<1|1,mid+1,r);
        e[i].v = e[i<<1].v+e[i<<1|1].v;
    }
    
    void modify(int i,int pos,int v) {
        if(pos> e[i].r||pos< e[i].l) return ;
        if(e[i].l == e[i].r) {
            e[i].v = v;
            return ;
        }
        modify(i<<1,pos,v);
        modify(i<<1|1,pos,v);
        e[i].v = e[i<<1].v+e[i<<1|1].v;
    }
    
    ll query(int i,int l,int r) {
        if(e[i].r< l||e[i].l> r) return 0;
        if(e[i].l>= l&&e[i].r<= r) return e[i].v;
        return query(i<<1,l,r)+query(i<<1|1,l,r);
    }
    
    ll demand(int x,int y) {
        int fx = top[x];
        int fy = top[y];
        ll ans = 0;
        while(fx!= fy) {
            if(deep[fx]< deep[fy]) {
                swap(fx,fy);
                swap(x,y);
            }
            ans+= query(1,p[fx],p[x]);
            x = fa[fx];
            fx = top[x];
        }
        if(x == y) return ans;
        if(deep[x]> deep[y]) swap(x,y);
        ans+= query(1,p[son[x]],p[y]);
        return ans;
    }
    
    void init() {
        sz = len = 0;
        mem(head,-1);
        for(int i = 0; i<= n; i++) pre[i] = i;
    }
    
    int main() {
        int t;
        cin>>t;
    
        while(t--) {
            int su,sv,sc,ss;
            scanf("%d %d",&n,&q);
            init();
            for(int i = 1; i<= n; i++) {
                int u,v,w;
                scanf("%d %d %d",&u,&v,&w);
                int fx = find(u);
                int fy = find(v);
    
                if(fx == fy) {
                    len+= 2;
                    ss = i;
                    su = u;
                    sv = v;
                    sc = w;
                    continue;
                } else
                    pre[fy] = fx;
                add(u,v,w);
                add(v,u,w);
            }
    
            dfs1(1,-1,1);
            dfs2(1,1);
    
            build(1,1,n);
    
            while(q--) {
                int o,x,y;
                scanf("%d %d %d",&o,&x,&y);
                if(o == 0) {
                    x--;
                    if(x == ss) {
                        sc = y;
                        continue;
                    }
                    modify(1,p[hold[x]],y);
                } else {
                    ll ans;
                    ans = sc+min(demand(x,su)+demand(y,sv),demand(x,sv)+demand(y,su));
                    ans = min(ans,demand(x,y));
                    printf("%lld
    ",ans);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    win7共享文件
    Linux之samba服务
    Linux之Apache服务
    Linux之ssh服务
    Linux基础入门之管理linux软件(rpm/yum)
    Linux基础入门之文件管理类命令
    PHP ssh链接sftp上传下载
    Black Hat Python之#2:TCP代理
    Black Hat Python之#1:制作简单的nc工具
    使用python的socket模块进行网络编程
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9557714.html
Copyright © 2020-2023  润新知