题意:给你一个n个点和m条边的带权无向图,查询每条边的MST。
思路:先求MST,在求的过程中建树,记录代价为ans。对每条边<u, v>权值记录为c,把它加进MST里面的代价就需要去掉u->lca(u, v)->v路径上权值最大的边记录权值为Max。那么结果就是ans - Max + c。
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (200000+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
int N, M;
struct LCA
{
struct Edge{
int from, to, val, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int depth[MAXN], fa[MAXN][20], Mx[MAXN][20];
void init(){
edgenum = 0;
CLR(head, -1);
}
void addEdge(int u, int v, int w)
{
Edge E = {u, v, w, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
void DFS(int u, int f, int d)
{
depth[u] = d; fa[u][0] = f;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == f)
{
Mx[u][0] = edge[i].val;
continue;
}
DFS(v, u, d+1);
}
}
void LCA_init()
{
DFS(1, -1, 0);
for(int i = 1; i < 20; i++)
{
for(int j = 1; j <= N; j++)
{
fa[j][i] = fa[fa[j][i-1]][i-1];
Mx[j][i] = max(Mx[j][i-1], Mx[fa[j][i-1]][i-1]);
}
}
}
int Get_path_max(int u, int v)
{
int ans = 0;
while(depth[u] != depth[v])
{
if(depth[u] < depth[v])
swap(u, v);
int d = depth[u] - depth[v];
for(int i = 0; i < 20; i++)
{
if(d >> i & 1)
{
ans = max(ans, Mx[u][i]);
u = fa[u][i];
}
}
}
if(u == v)
return ans;
for(int i = 19; i >= 0; i--)
{
if(fa[u][i] != fa[v][i])
{
ans = max(ans, Mx[u][i]);
ans = max(ans, Mx[v][i]);
u = fa[u][i];
v = fa[v][i];
}
}
return max(ans, max(Mx[u][0], Mx[v][0]));
}
};
LCA L;
struct Union
{
int pre[MAXN];
void init()
{
for(int i = 1; i <= N; i++)
pre[i] = i;
}
int Find(int p)
{
int child = p;
while(p != pre[p])
p = pre[p];
while(child != p)
{
int t = pre[child];
pre[child] = p;
child = t;
}
return p;
}
};
Union U;
struct Node{
int u, v, w;
};
Node num[MAXM];
bool cmp(Node a, Node b){
return a.w < b.w;
}
int a[MAXN], b[MAXN], c[MAXN];
int main()
{
Ri(N); Ri(M);
U.init(); L.init();
int top = 0;
for(int i = 1; i <= M; i++)
{
Ri(a[i]); Ri(b[i]); Ri(c[i]);
num[top].u = a[i]; num[top].v = b[i]; num[top++].w = c[i];
}
sort(num, num+top, cmp);
LL ans = 0;
for(int i = 0; i < top; i++)
{
int u = U.Find(num[i].u);
int v = U.Find(num[i].v);
if(u != v)
{
L.addEdge(num[i].u, num[i].v, num[i].w);
L.addEdge(num[i].v, num[i].u, num[i].w);
ans += num[i].w;
U.pre[u] = v;
}
}
L.LCA_init();
for(int i = 1; i <= M; i++)
{
int Max = L.Get_path_max(a[i], b[i]);
Pl(ans - Max + c[i]);
}
return 0;
}