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;
    }
  • 相关阅读:
    Java编程思想小笔记
    JAVA中的访问权限
    重写equals、hashCode
    JAVA核心技术I之接口与内部类
    JAVA核心技术I之继承
    javascript日志-array数组去重
    vue练习项目
    vue日志-axios跨域获取豆瓣api
    在vue-cli中安装scss,且可以全局引入scss的步骤
    css参考手册
  • 原文地址:https://www.cnblogs.com/planche/p/8910844.html
Copyright © 2011-2022 走看看