zoukankan      html  css  js  c++  java
  • codeforces 609E Minimum spanning tree for each edge

    E. Minimum spanning tree for each edge
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Connected undirected weighted graph without self-loops and multiple edges is given. Graph contains n vertices and m edges.

    For each edge (u, v) find the minimal possible weight of the spanning tree that contains the edge (u, v).

    The weight of the spanning tree is the sum of weights of all edges included in spanning tree.

    Input

    First line contains two integers n and m (1 ≤ n ≤ 2·105, n - 1 ≤ m ≤ 2·105) — the number of vertices and edges in graph.

    Each of the next m lines contains three integers ui, vi, wi (1 ≤ ui, vi ≤ n, ui ≠ vi, 1 ≤ wi ≤ 109) — the endpoints of the i-th edge and its weight.

    Output

    Print m lines. i-th line should contain the minimal possible weight of the spanning tree that contains i-th edge.

    The edges are numbered from 1 to m in order of their appearing in input.

    Sample test(s)
    input
    5 7
    1 2 3
    1 3 1
    1 4 5
    2 3 2
    2 5 3
    3 4 2
    4 5 4
    output
    9
    8
    11
    8
    8
    8
    9

    保证某条边e存在的MST就是普通Kruskal把e优先到了最前面。

    先求一遍MST,如果e不再MST上,是因为形成了环,把环上除了e的最大权边去掉就好了。

    (以前的LCA:用ST来RMQ,查询O(1)

    (向祖先结点倍增其实和ST差不多,查询O(logn),维护信息灵活

    (一开始想的是树剖,复杂度稍高

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    const int N = 2e5+5, M = N*2;
    
    int pa[N], rak[N];
    int fd(int x){ return pa[x] ? pa[x] = fd(pa[x]) : x; }
    bool unite(int x,int y)
    {
        int a = fd(x), b = fd(y);
        if(a == b) return false;
        if(rak[a] < rak[b]){
            pa[a] = b;
        }
        else {
            pa[b] = a;
            if(rak[a] == rak[b]) rak[a]++;
        }
        return true;
    }
    
    int fro[N], to[N], we[N];
    
    int hd[N];
    int nx[M], ver[M], wei[M];
    int ec;
    
    void add_e(int u,int v,int w)
    {
        ver[++ec] = v;
        wei[ec] = w;
        nx[ec] = hd[u];
        hd[u] = ec;
    }
    
    int n, m;
    int *cmp_c;
    bool cmp_id(int i,int j){ return cmp_c[i] < cmp_c[j]; }
    
    int r[N];
    ll kruskal()
    {
        ll re = 0;
        int i,j;
        for(i = 1; i <= m; i++) r[i] = i;
        cmp_c = we;
        sort(r+1, r + 1 + m, cmp_id);
        //ec = 0;
        for(i = 1; i <= m; i++){
            j = r[i];
            if(unite(fro[j],to[j])){
                add_e(fro[j],to[j],we[j]);
                add_e(to[j],fro[j],we[j]);
                re += we[j];
                we[j] = 0;
            }
        }
        return re;
    }
    
    const int LOG = 19;
    
    int fa[N][LOG], mx[N][LOG];
    int dep[N];
    
    void dfs(int u,int f = 0,int fw = 0,int d = 0)
    {
        fa[u][0] = f;
        mx[u][0] = fw;
        dep[u] = d;
        for(int i = hd[u]; i; i = nx[i]) {
            int v = ver[i];
            if(v == f) continue;
            dfs(v,u,wei[i],d+1);
        }
    }
    
    int lg;
    
    int queryMx(int u,int v)
    {
        int re = 0, i;
        if(dep[u] < dep[v]) swap(u,v);
        for(i = lg; i >= 0; i--) if(dep[u] - (1<<i) >= dep[v]){
            re = max(re,mx[u][i]);
            u = fa[u][i];
        }
        if(u == v) return re;
        for(i = lg; i >= 0; i--) if(fa[u][i] != fa[v][i]){
            re = max(re,max(mx[u][i],mx[v][i]));
            u = fa[u][i];
            v = fa[v][i];
        }
        return max(re,max(mx[u][0],mx[v][0]));
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        //cout<<log2(N);
        scanf("%d%d",&n,&m);
        int i,j;
        for(i = 1; i <= m; i++){
            scanf("%d%d%d",fro+i,to+i,we+i);
        }
        ll mst = kruskal();
    
        dfs(1);
        lg = ceil(log2(n));
        for(j = 1; j <= lg; j++){
            for(i = 1; i <= n; i++) if(fa[i][j-1]){
                fa[i][j] = fa[fa[i][j-1]][j-1];
                mx[i][j] = max(mx[i][j-1],mx[fa[i][j-1]][j-1]);
            }
        }
        for(i = 1; i <= m; i++) {
            printf("%I64d
    ",we[i]?mst + we[i] - queryMx(fro[i],to[i]):mst);
        }
        return 0;
    }
  • 相关阅读:
    Linux网络检测手段汇总
    Hadoop单机搭建
    Nginx之Location模块
    关于STM32驱动DS1302实时时钟的一点思考
    灵感手环第一步——0.96寸OLED显示实验
    把简单做到极致
    KEIL MDK 查看代码量、RAM使用情况--RO-data、RW-data、ZI-data
    关于SPI通信原理与程序实现
    【转载】keil5中加入STM32F10X_HD,USE_STDPERIPH_DRIVER的原因
    关于keil5使用注意事项(预定义、路径包含)
  • 原文地址:https://www.cnblogs.com/jerryRey/p/5071528.html
Copyright © 2011-2022 走看看