E. Minimum spanning tree for each edge(MST+LCA)

**
题目传送门
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·10^5, n - 1 ≤ m ≤ 2·10^5) — 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

题意

n个点,m条边,给出每条边的起点,终点和边权值,针对每条边,求一定有这条边的MST(最小生成树),最后输出MST的权值。

思路

朴素解法就是对每条边跑一边MST,很根据数据量会TLE。

那优化一下,我们可以发现所有的边分成两种情况,一种是在整图的MST中,另一种是不在整图的MST中的。
第一种情况:先对整图跑一遍MST,边跑边记录MST的边,如果求的边正好在MST中,那直接输出W(MST的权值)即可。
第二种情况:如果不在MST中的话,那我们就把这条边添加进MST中,那么一定会成环,接下来我们只需要把这个环中除去刚添加进的那条边之外的最大权值的那条边去掉,那么就会出现一棵新的包含该边的生成树。

那么问题来了!!!
怎么找到要去掉的那条边呢?LCA可以解决我们的问题。
附加一个大佬对LCA的讲解+模板:LCA
最基础的LCA可以维护某点的第2^j
个祖先节点,我们可以另外维护一个Max[i][j]数组,代表i到第2^j祖先节点的最大距离。综上所述,我们就可以求出第二种情况的权值,即ans=MST_W-LCA(u,v)+w(各个参数详见代码)
在这里插入图片描述

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 6;
const int LOG = 25;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int n, m;
ll MST_W;
int fa[MAXN];
int root;
int anc[MAXN][LOG], dep[MAXN];
ll Max[MAXN][LOG];
struct Edge
{
   
	int id;
	int u, v, w;
	bool isMST;
	ll minn;
};
vector<Edge>E;
vector<Edge>ve[MAXN];
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值