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;
    }
  • 相关阅读:
    Struts2声明式异常处理
    几种常用的过滤器
    Jdk 和 Tomcat的 安装。(旧版本,请看新版本3篇)
    java 判断字符串是否相等
    PreparedStatement 查询 In 语句 setArray 等介绍。
    String、StringBuffer与StringBuilder之间区别
    IntelliJ IDEA 里 查看一个函数注释的方法是 ctrl+q
    Java字符串拼接效率对比
    Java 中判断字符串是否为空
    IntelliJ IDEA + Tomcat ;On Upate Action 与 On Frame Deactivation
  • 原文地址:https://www.cnblogs.com/planche/p/8910844.html
Copyright © 2011-2022 走看看