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
  • 相关阅读:
    一张图片入门Python
    4.1. 如何在Windows环境下开发Python
    你必须知道的EF知识和经验
    XUnit的使用
    如何使用NUnit
    Entity Framework 不支持DefaultValue
    Have You Ever Wondered About the Difference Between NOT NULL and DEFAULT?
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Entity Framework 与多线程
    sqlite中的自增主键
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9889654.html
Copyright © 2011-2022 走看看