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\n", tmp+s[i].w-max(cal(s[i].a, ans[i]), cal(s[i].b, ans[i])));
    return 0;
}

 

posted @ 2018-04-22 23:27  planche  阅读(247)  评论(0编辑  收藏  举报