题目链接:http://codeforces.com/contest/609/problem/E
题意:给一个无向图,n个点,m条边,对任意边edge[i],求出包含有边edge[i]的最小生成树。
解法:考虑MST的性质,对任意两点u,v一定有且只有一条路径,当边[u,v]不是MST边的时候,加入边[u,v]便
会形成环,于是在u到v的路径上找一条权值最大的边删去再加入边[u,v],之前环上的任意两点仍然连通。
u到v路径的最大值用LCA来维护。
//CF 609E
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
struct edge1{
int u, v, w, id;
}E1[maxn*2];
struct edge2{
int v, w, nxt;
}E2[maxn*2];
int head[maxn], edgecnt, n, m;
void init(){
memset(head, -1, sizeof(head));
edgecnt=0;
}
void add(int u, int v, int w){
E2[edgecnt].v = v, E2[edgecnt].w = w,E2[edgecnt].nxt = head[u], head[u] = edgecnt++;
}
int pa[maxn];
int find_set(int x){
if(x == pa[x]) return x;
else return pa[x] = find_set(pa[x]);
}
bool cmp(const edge1 &a, const edge1 &b){
return a.w < b.w;
}
long long build(){
sort(E1+1, E1+m+1, cmp);
for(int i=1;i<=n;i++) pa[i]=i;
int cnt=0;
long long ans=0;
for(int i=1; i<=m; i++){
int x=E1[i].u, y=E1[i].v;
int fx = find_set(x), fy = find_set(y);
if(fx==fy) continue;
add(E1[i].u, E1[i].v, E1[i].w);
add(E1[i].v, E1[i].u, E1[i].w);
pa[fx]=fy;
ans+=E1[i].w;
cnt++;
if(cnt==n-1) break;
}
return ans;
}
int dep[maxn],p[20][maxn],maxv[20][maxn];
void dfs(int u,int f,int d,int w)
{
dep[u]=d;
p[0][u]=f,maxv[0][u]=w;
for(int i=head[u]; ~i; i=E2[i].nxt)
{
int v=E2[i].v;
if(v==f) continue;
dfs(v,u,d+1,E2[i].w);
}
}
void build2()
{
dfs(1,-1,0,0);
for(int i=0; i+1<18; i++)
{
for(int v=1; v<=n; v++)
{
if(p[i][v]<0) p[i+1][v]=-1;
else p[i+1][v]=p[i][p[i][v]];
maxv[i+1][v] = max(maxv[i][v],maxv[i][p[i][v]]);
}
}
}
int lca(int u,int v)
{
if(dep[u]>dep[v]) swap(u,v);
for(int i=0; i<18; i++) if(dep[u]-dep[v]>>i&1) v=p[i][v];
if(u==v) return u;
for(int i=17; ~i; i--)
if(p[i][u]!=p[i][v])
u=p[i][u],v=p[i][v];
return p[0][u];
}
int get(int u,int to)
{
int ret=0;
for(int i=0; i<18; i++)
if(dep[u]-dep[to]>>i&1) ret=max(ret,maxv[i][u]),u=p[i][u];
return ret;
}
long long ans[maxn];
int main()
{
scanf("%d%d", &n, &m);
init();
for(int i=1; i<=m; i++){
scanf("%d%d%d", &E1[i].u, &E1[i].v, &E1[i].w);
E1[i].id = i;
}
long long mst = build();
build2();
for(int i=1; i<=m; i++){
int _lca = lca(E1[i].u, E1[i].v);
int xx = max(get(E1[i].u, _lca), get(E1[i].v, _lca));
ans[E1[i].id] = mst-xx+E1[i].w;
}
for(int i=1; i<=m; i++){
printf("%lld\n", ans[i]);
}
return 0;
}