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

    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.

    Examples

    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

    次小生成树模板:
    lca+倍增+最小生成树
    #define eps 1e-6
    #define ll long long
    #define pii pair<int, int>
    #define pb push_back
    #define mp make_pair
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    const int N = 200100;
    //*************************
    int n, m;
    //kruscal
    struct tree
    {
        int a,b,w;
    } p[N],s[N];
    int p1[N];
    int rk1[N];
    //倍增
    int fa[N][20], max_e[N][20], dep[N];
    //lca
    struct edge
    {
        int to, nxt,w;
    } e[N<<1];
    int fst[N], tot;
    struct query
    {
        int to,nxt;
        int idx;
    } Q[N<<1];
    int h[N],tt;
    int p2[N],rk2[N];
    int acr[N], ans[N];
    bool vis[N];
    //************************
    void CLS()
    {
        tot = 0;
        memset(fst,-1,sizeof(fst));
        tt = 0;
        for(int i=1; i<=n; i++)p1[i]=i,p2[i]=i;
        memset(h,-1,sizeof(h));
    }
    void add(int u,int v,int w)
    {
        e[++tot].to = v;
        e[tot].w = w;
        e[tot].nxt = fst[u];
        fst[u] = tot;
    }
    void add_Q(int u,int v,int idx)
    {
        Q[++tt].to = v;
        Q[tt].nxt = h[u];
        Q[tt].idx = idx;
        h[u] = tt;
    }
    //kruscal
    bool cmp(tree x,tree y)
    {
        return x.w<y.w;
    }
    int find_p(int x)
    {
        return x == p1[x] ? x : p1[x]=find_p(p1[x]);
    }
    void uone1(int x,int y)
    {
        int t1=find_p(x);
        int t2=find_p(y);
        if(t1!=t2)
        {
            if(rk1[t1]>rk1[t2])p1[t2]=t1;
            else p1[t1]=t2;
            if(rk1[t1]==rk1[t2])rk1[t2]++;
        }
    }
    ll kruscal()
    {
        ll res = 0;
        sort(p+1, p+m+1, cmp);
        int cnt=0;
        for (int i = 1; i <= m; i++)
        {
            int x=p[i].a;
            int y=p[i].b;
            int w=p[i].w;
            if(find_p(x)!=find_p(y))
            {
                cnt++;
                uone1(x,y);
                res+=w;
                add(x,y,w);
                add(y,x,w);
                if(cnt==n-1)break;
            }
        }
        return res;
    }
    
    //倍增
    void init_fa(int u, int p, int w)
    {
        dep[u] = dep[p] + 1;
        fa[u][0] = p;
        max_e[u][0] = w;
        for (int i = 1; fa[u][i-1]; i++)
        {
            fa[u][i] = fa[ fa[u][i-1] ][i-1];
            max_e[u][i] = max(max_e[u][i-1], max_e[ fa[u][i-1] ][i-1]);
        }
    }
    
    int cal(int u, int lca)
    {
        int d = dep[u] - dep[lca];
        int res = 0;
        for(int i = 18; i >= 0; i--)
        {
            if ((1<<i) <= d)
            {
                d -= (1<<i);
                res = max(res, max_e[u][i]);
                u = fa[u][i];
            }
        }
        return res;
    }
    
    //LCA
    int find_q(int x)
    {
        return x == p2[x] ? x : p2[x]=find_q(p2[x]);
    }
    void uone2(int x,int y)
    {
        int t1=find_q(x);
        int t2=find_q(y);
        if(t1!=t2)
        {
            if(rk2[t1]>rk2[t2])p2[t2]=t1;
            else p2[t1]=t2;
            if(rk2[t1]==rk2[t2])rk2[t2]++;
        }
    }
    void LCA(int u)
    {
        vis[u] = 1;
        acr[u] = u;
        for(int p = fst[u]; p != -1; p = e[p].nxt)
        {
            int v = e[p].to;
            if(vis[v]) continue;
            init_fa(v, u, e[p].w);
            LCA(v);
            uone2(u,v);
            acr[find_q(u)] = u;
        }
        for(int p = h[u]; p != -1; p = Q[p].nxt)
        {
            int v = Q[p].to;
            if(vis[v]) ans[Q[p].idx] = acr[find_q(v)];
        }
    }
    
    int main()
    {
    //    freopen("input.txt", "r", stdin);
        scanf("%d%d", &n, &m);
        CLS();
        for (int i = 1; i <= m; i++)
        {
            int a,b,w;
            scanf("%d%d%d",&a,&b,&w);
            p[i].a=s[i].a=a;
            p[i].b=s[i].b=b;
            p[i].w=s[i].w=w;
            add_Q(a,b,i);
            add_Q(b,a,i);
        }
        ll tmp = kruscal();
        LCA(1);
        for (int i = 1; i <= m; i++)
            printf("%I64d
    ", tmp+s[i].w-max(cal(s[i].a, ans[i]), cal(s[i].b, ans[i])));
        return 0;
    }
  • 相关阅读:
    NET ERP系统架构设计
    WebApi的一种集成测试写法(in-memory)
    开发类工具
    GitHub版本控制
    TortoiseGit安装与配置(转)
    tortoisegit使用密钥连接服务器(转)
    重构一个功能块的总结
    脚本绘图工具总结(转)
    Oracle 多表关联更新
    数据结构与算法之递推算法 C++与PHP实现
  • 原文地址:https://www.cnblogs.com/planche/p/8910844.html
Copyright © 2011-2022 走看看