**
题目传送门
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];