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.
Example
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
题意:给一个图,有m条边n个点,如果对于一个最小生成树中要求必须包括第i条边,那么最小生成树的权值总和最小是多少
思路:求出最小生成树,然后对于m条边相当于m次查询,每次查询的时候,相当于求出在最小生成树中(u,v)路径上的边权最大值,那么新添加了一条边,就要把这条最大值的边删掉。所以题目转换成了,求路径上边权最大值。可以用LCA来做,也可以用树链剖分来维护。
遗忘点1,fa的父根应该是父节点
遗忘点2,一开始全标记为-1,然后加个判断消掉根节点的影响。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
typedef long long ll;
int mx[N][21],fa[N][21],f[N],deep[N];
int tot,n,m,head[N];
ll ans[N];
ll mincost;
struct node{
int x,y,w,id;
}bian[N+100];
struct Edge
{
int v,nxt,w;
}E[2*N+300];
void init()
{
memset(head,-1,sizeof(head));
memset(fa,-1,sizeof(fa));
memset(deep,0,sizeof(deep));
for(int i=1;i<=n;i++)
f[i]=i;
tot=0;
mincost=0;
}
int cmp(node a,node b){
return a.w<b.w;
}
int find(int x)
{
return x==f[x]?f[x]:f[x]=find(f[x]);
}
void add(int u,int v,int w)
{
E[tot].v=v;
E[tot].w=w;
E[tot].nxt=head[u];
head[u]=tot++;
}
void merge(int x,int y,int c)
{
int f1=find(x);
int f2=find(y);
if(f1!=f2)
{
f[f1]=f2;
add(x,y,c);
add(y,x,c);
mincost+=c;
}
}
void dfs(int x,int de)
{
deep[x]=de;
for(int i=head[x];i!=-1;i=E[i].nxt)
{
int vv=E[i].v;
if(!deep[vv])
{
fa[vv][0]=x;//遗忘点1,fa的父根应该是父节点
mx[vv][0]=E[i].w;
dfs(vv,de+1);
}
}
}
void ST()
{
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i<=n;i++)
{
if(fa[i][j-1]!=-1)//遗忘点2,一开始全标记为-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]);
}
}
}
}
int lca(int a,int b)
{
if(deep[a]<deep[b]) swap(a,b);
int t=deep[a]-deep[b];
int maxx=0;
for(int i=0;i<=20;i++)
{
if((1<<i)&t)
{
maxx=max(maxx,mx[a][i]);
a=fa[a][i];
}
}
if(a==b) return maxx;
for(int i=20;i>=0;i--)
{
if(fa[a][i]!=fa[b][i])
{
maxx=max(maxx,mx[a][i]);
maxx=max(maxx,mx[b][i]);
a=fa[a][i];
b=fa[b][i];
}
}
maxx=max(mx[a][0],maxx);
maxx=max(mx[b][0],maxx);
return maxx;
}
int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
bian[i].x=a,bian[i].y=b;
bian[i].w=c,bian[i].id=i;
}
sort(bian+1,bian+1+m,cmp);
for(int i=1;i<=m;i++)
{
merge(bian[i].x,bian[i].y,bian[i].w);
}
dfs(1,1);
ST();
for(int i=1;i<=m;i++)
{
ans[bian[i].id]=mincost-(ll)lca(bian[i].x,bian[i].y)+(ll)bian[i].w;
}
for(int i=1;i<=m;i++)
{
printf("%lld\n",ans[i] );
}
}