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
  • 相关阅读:
    PCA与LDA
    SVM--交叉验证
    git的基本使用
    MySQL的操作
    MySQL安装和远程连接
    javaScript进阶
    javaScript基础入门篇
    javaScript运动
    可变对象和不可变对象
    基本数据类型
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9889654.html
Copyright © 2011-2022 走看看