zoukankan      html  css  js  c++  java
  • Codeforces 827D Best Edge Weight 倍增 + 并查集 || 倍增 + 压倍增标记 (看题解)

    Best Edge Weight

    我们先找出一棵最小生成树,

    对于非树边来说, 答案就是两点路径上的最大值 - 1, 这个直接倍增就能处理。

    对于树边来说, 就是非树边的路径经过这条边的最小值 - 1, 这个可以用并查集压缩路径 或者 更压st表一样的方式更新。

    感觉就是没想到先扣出来一个最小生成树, 而是往克鲁斯卡尔的过程中想了。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    int n, m;
    vector<PII> G[N];
    bool can[N];
    int ans[N];
    int pathMin[N];
    
    struct Edge {
        int u, v, c, id;
        bool operator < (const Edge &rhs) const {
            return c < rhs.c;
        }
    } e[N];
    
    int fa[N];
    int getRoot(int x) {
        return fa[x] == x ? x : fa[x] = getRoot(fa[x]);
    }
    
    int pa[N][20], mx[N][20], depth[N];
    
    void dfs(int u, int fa, int w) {
        depth[u] = depth[fa] + 1;
        pa[u][0] = fa; mx[u][0] = w;
        for(int i = 1; i < 20; i++)
            pa[u][i] = pa[pa[u][i - 1]][i - 1];
        for(int i = 1; i < 20; i++)
            mx[u][i] = max(mx[u][i - 1], mx[pa[u][i - 1]][i - 1]);
        for(auto& e : G[u]) {
            if(e.se == fa ) continue;
            dfs(e.se, u, e.fi);
        }
    }
    
    int getMaxWei(int u, int v) {
        if(depth[u] < depth[v]) swap(u, v);
        int dis = depth[u] - depth[v];
        int ans = 0;
        for(int i = 19; i >= 0; i--)
            if(dis >> i & 1) chkmax(ans, mx[u][i]), u = pa[u][i];
        if(u == v) return ans;
        for(int i = 19; i >= 0; i--) {
            if(pa[u][i] != pa[v][i]) {
                chkmax(ans, mx[u][i]);
                chkmax(ans, mx[v][i]);
                u = pa[u][i];
                v = pa[v][i];
            }
        }
        chkmax(ans, mx[u][0]);
        chkmax(ans, mx[v][0]);
        return ans;
    }
    
    int getLca(int u, int v) {
        if(depth[u] < depth[v]) swap(u, v);
        int dis = depth[u] - depth[v];
        for(int i = 19; i >= 0; i--)
            if(dis >> i & 1) u = pa[u][i];
        if(u == v) return u;
        for(int i = 19; i >= 0; i--)
            if(pa[u][i] != pa[v][i])
                u = pa[u][i], v = pa[v][i];
        return pa[u][0];
    }
    
    void gao(int u, int v, int c) {
        while(1) {
            u = getRoot(u);
            if(depth[u] <= depth[v]) break;
            pathMin[u] = c;
            int nex = getRoot(pa[u][0]);
            fa[u] = nex;
            u = nex;
        }
    }
    
    int main() {
        memset(pathMin, 0x3f, sizeof(pathMin));
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) fa[i] = i;
        for(int i = 1; i <= m; i++) {
            scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c);
            e[i].id = i;
        }
        sort(e + 1, e + 1 + m);
        for(int i = 1; i <= m; i++) {
            int u = e[i].u, v = e[i].v, c = e[i].c, id = e[i].id;
            int x = getRoot(u);
            int y = getRoot(v);
            if(x != y) {
                can[i] = true;
                fa[y] = x;
                G[u].push_back(mk(c, v));
                G[v].push_back(mk(c, u));
            }
        }
    
        dfs(1, 0, 0);
    
        for(int i = 1; i <= n; i++) fa[i] = i;
        for(int i = 1; i <= m; i++) {
            if(can[i]) continue;
            int u = e[i].u, v = e[i].v, c = e[i].c, id = e[i].id;
            int lca = getLca(u, v);
            gao(u, lca, c);
            gao(v, lca, c);
        }
    
        for(int i = 1; i <= m; i++) {
            int u = e[i].u, v = e[i].v, c = e[i].c, id = e[i].id;
            if(!can[i]) {
                ans[id] = getMaxWei(u, v) - 1;
            } else {
                if(depth[u] < depth[v]) swap(u, v);
                ans[id] = pathMin[u] == inf ? -1 : pathMin[u] - 1;
            }
        }
    
        for(int i = 1; i <= m; i++)
            printf("%d%c", ans[i], " 
    "[i == m]);
        return 0;
    }
    
    /*
    
    */
  • 相关阅读:
    poj1978
    poj3505
    免费专利讲座
    没有找到MFC80UD.DLL"没有找到MFC80UD.DLL,
    新手学C++/CLI及C#
    怎样激发技术人员的创新力?
    关于大型asp.net应用系统的架构—如何做到高性能高可伸缩性
    绝好的一套针对初学者的JavaScript教程
    VC如何将自身进程提升至管理员权限
    如何寻找优秀的专利代理人
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10956883.html
Copyright © 2011-2022 走看看