zoukankan      html  css  js  c++  java
  • CF609E Minimum spanning tree for each edge

    原来觉得是一个LCT,感觉自己瞬间傻掉……

    考虑到先做一个最小生成树求出做最小生成树的代价$ans$,顺便标记一下树边和非树边,把边按照输入$id$排序回去之后扫,如果扫到一条树边,那么此时的答案就是$ans$,如果扫到一条非树边,那么相当于一条边强制连上之后再切去环里的一条边使这个基环树重新变成一棵树,那么贪心一下,肯定要切掉最大的边,而这个断开一个口的环其实就是树上的一条路径,这个过程只要倍增就可以维护。

    时间复杂度$O(nlogn)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N = 2e5 + 5;
    const int Lg = 20;
    
    int n, m, dep[N], fa[N][Lg], tot = 0, head[N], ufs[N];
    ll ans = 0LL, maxn[N][Lg];
    
    struct Edge {
        int to, nxt;
        ll val;
    } e[N << 1];
    
    inline void add(int from, int to, int val) {
        e[++tot].to = to;
        e[tot].val = val;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    struct Pathway {
        int u, v, id;
        ll val;
        bool inTree;
    } path[N];
    
    bool cmpv(const Pathway &x, const Pathway &y) {
        return x.val < y.val;
    }
    
    bool cmpi(const Pathway &x, const Pathway &y) {
        return x.id < y.id;
    }
    
    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;
    }
    
    inline ll max(ll x, ll y) {
        return x > y ? x : y;
    }
    
    inline void chkMax(ll &x, ll y) {
        if(y > x) x = y;
    }
    
    inline void init() {
        for(int i = 1; i <= n; i++) ufs[i] = i;
    }
    
    int find(int x) {
        return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
    }
    
    inline void kruskal() {
        init();
        sort(path + 1, path + 1 + m, cmpv);
        for(int cnt = 0, i = 1; i <= m; i++) {
            int u = find(path[i].u), v = find(path[i].v);
            if(u == v) continue;
            cnt++, ufs[u] = v, path[i].inTree = 1, ans += path[i].val;
            add(path[i].u, path[i].v, path[i].val), add(path[i].v, path[i].u, path[i].val);
            if(cnt >= n - 1) break;
        }
    }
    
    void dfs(int x, int fat, int depth, ll nowDis) {
        fa[x][0] = fat, dep[x] = depth, maxn[x][0] = nowDis;
        for(int i = 1; i <= 18; i++) {
            fa[x][i] = fa[fa[x][i - 1]][i - 1];
            maxn[x][i] = max(maxn[fa[x][i - 1]][i - 1], maxn[x][i - 1]);
        }
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            dfs(y, x, depth + 1, e[i].val);
        }
    }
    
    inline void swap(int &x, int &y) {
        int t = x;
        x = y;
        y = t;
    }
    
    inline ll getMax(int x, int y) {
        if(dep[x] < dep[y]) swap(x, y);
        ll res = 0LL;
        for(int i = 18; i >= 0; i--)
            if(dep[fa[x][i]] >= dep[y])
                chkMax(res, maxn[x][i]), x = fa[x][i];
        if(x == y) return res;
        for(int i = 18; i >= 0; i--)  
            if(fa[x][i] != fa[y][i]) {
                chkMax(res, maxn[x][i]);
                chkMax(res, maxn[y][i]);
                x = fa[x][i], y = fa[y][i];
            }
        return max(res, max(maxn[x][0], maxn[y][0]));
    }
    
    inline void solve() {
        sort(path + 1, path + 1 + m, cmpi);
        
    /*    for(int i = 1; i <= m; i++)
            printf("%d %d %lld %d
    ", path[i].u, path[i].v, path[i].val, path[i].inTree);
        printf("
    %lld
    ", ans);   */
        
        for(int i = 1; i <= m; i++) {
            if(path[i].inTree) printf("%lld
    ", ans);
            else printf("%lld
    ", ans - getMax(path[i].u, path[i].v) + path[i].val);
        }
    }
    
    int main() {
        read(n), read(m);
        for(int i = 1; i <= m; i++) {
            read(path[i].u), read(path[i].v), read(path[i].val);
            path[i].id = i, path[i].inTree = 0;
        }
        
        kruskal();
        dfs(1, 0, 1, 0LL);
        solve();
        
        return 0;
    }
    View Code
  • 相关阅读:
    2、Windows 系统下安装 IntelliJ IDEA
    1、IntelliJ IDEA 使用说明
    C# static的用法详解
    wpf 加载窗体界面时出现异常System.IO.FileNotFoundException
    ObservableCollection绑定到TextBox
    Lambda表达式(转载)
    C#中out和ref之间的区别 转载
    WPF序列化与反序列化
    软件版本号规范与命名原则 转载
    WPF DataGrid滚动条滑动的时候背景色错乱或显示不全
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9531600.html
Copyright © 2011-2022 走看看