zoukankan      html  css  js  c++  java
  • Luogu 4949 最短距离

    这就是个水题。

    一开始想把整个环找出来断开当一条链,然后其他部分正常链剖,两个点之间的路径如果经过环就考虑一下走哪边更快。

    但是这样子还是太麻烦了。

    我们可以直接断开环上的一条边,然后正常链剖,只要在查询的时候强制走这条边然后取个$min$就好了。

    时间复杂度$O(nlog^2n)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5 + 25;
    
    int n, qn, tot = 0, head[N], ufs[N], sx, sy, sid, pid[N];
    int dfsc = 0, id[N], siz[N], son[N], fa[N], top[N], dep[N];
    ll sv, eVal[N], w[N];
    
    struct Edge {
        int to, nxt, eid;
        ll val;
    } e[N << 1];
    
    inline void add(int from, int to, int eid, ll val) {
        e[++tot].to = to;
        e[tot].eid = eid;
        e[tot].val = val;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    template <typename T>
    inline void chkMin(T &x, T y) {
        if(y < x) x = y;
    }
    
    template <typename T>
    inline void swap(T &x, T &y) {
        T t = x; x = y; y = t;
    }
    
    int find(int x) {
        return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
    }
    
    void dfs1(int x, int fat, int depth) {
        fa[x] = fat, dep[x] = depth, siz[x] = 1;
        int maxson = -1;
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            pid[e[i].eid] = y;
            eVal[y] = e[i].val;
            dfs1(y, x, depth + 1);
            
            siz[x] += siz[y];
            if(siz[y] > maxson) 
                maxson = siz[y], son[x] = y;
        }
    }
    
    void dfs2(int x, int topf) {
        top[x] = topf, w[id[x] = ++dfsc] = eVal[x];
        if(!son[x]) return;
        dfs2(son[x], topf);
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fa[x] || y == son[x]) continue;
            dfs2(y, y);
        }
    }
    
    namespace Bit {
        ll s[N];
        
        #define lowbit(p) (p & (-p))
        
        inline void modify(int p, ll v) {
            for(; p <= n; p += lowbit(p))
                s[p] += v;
        }
        
        inline ll getSum(int p) {
            ll res = 0LL;
            for(; p > 0; p -= lowbit(p))
                res += s[p];
            return res;
        }
        
        inline ll query(int l, int r) {
            return getSum(r) - getSum(l - 1);
        }
        
    } using namespace Bit;
    
    inline ll getDis(int x, int y) {
        ll res = 0LL;
        for(; top[x] != top[y]; ) {
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            res += query(id[top[x]], id[x]);
            x =fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        res += query(id[x] + 1, id[y]);
        return res;
    }
    
    int main() {
        read(n), read(qn);
        for(int i = 1; i <= n; i++) ufs[i] = i;
        for(int i = 1; i <= n; i++) {
            int x, y; ll v;
            read(x), read(y), read(v);
            int fx = find(x), fy = find(y);
            if(fx != fy) {
                ufs[fx] = fy; 
                add(x, y, i, v), add(y, x, i, v);
            } else 
                sx = x, sy = y, sv = v, sid = i;
        }
        
        dfs1(1, 0, 1), dfs2(1, 1);
        
    /*    for(int i = 1; i <= n; i++)
            printf("%lld
    ", eVal[i]);
        printf("
    ");   */
        
        for(int i = 1; i <= n; i++)
            if(w[i]) modify(i, w[i]);
        
        for(int op; qn--; ) {
            read(op);
            if(op == 1) {
                int x; ll v;
                read(x), read(v);
                if(x == sid) sv = v;
                else {
                    modify(id[pid[x]], -eVal[pid[x]]);
                    eVal[pid[x]] = v;
                    modify(id[pid[x]], v);
                }
            } else {
                int x, y;
                read(x), read(y);
                ll res = getDis(x, y);
                chkMin(res, getDis(x, sx) + getDis(y, sy) + sv);
                chkMin(res, getDis(x, sy) + getDis(y, sx) + sv);
                printf("%lld
    ", res);
            }
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    【Codeforces 349B】Color the Fence
    【Codeforces 459D】Pashmak and Parmida's problem
    【Codeforces 467C】George and Job
    【Codeforces 161D】Distance in Tree
    【Codeforces 522A】Reposts
    【Codeforces 225C】Barcode
    【Codeforces 446A】DZY Loves Sequences
    【Codeforces 429B】Working out
    【Codeforces 478C】Table Decorations
    【Codeforces 478C】Table Decorations
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9889654.html
Copyright © 2011-2022 走看看