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.c++

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

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

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.spa

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.code

Output

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

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

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優先到了最前面。ip

先求一遍MST,若是e再也不MST上,是由於造成了環,把環上除了e的最大權邊去掉就行了。ci

(之前的LCA:用ST來RMQ,查詢O(1)input

(向祖先結點倍增其實和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\n",we[i]?mst + we[i] - queryMx(fro[i],to[i]):mst);
    }
    return 0;
}
相關文章
相關標籤/搜索