[CF609E]Minimum spanning tree for each edge

Posted memory-of-winter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF609E]Minimum spanning tree for each edge相关的知识,希望对你有一定的参考价值。

题目大意:有一张$n$个点$m$条边的图,要求对于每条边求出包含这条边的最小生成树

题解:先求出最小生成树,发现加入一条不在最小生成树上的边,就会出现一个环,那么把这个环上除这条边外权值最大的一条边删去就是对于这条边的最小生成树,可以倍增求

卡点:倍增结尾处理错

 

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 200010

int head[maxn], cnt;
struct Edge {
	int to, nxt, w;
} e[maxn << 1];
inline void add(int a, int b, int c) {
	e[++cnt] = (Edge) {b, head[a], c}; head[a] = cnt;
	e[++cnt] = (Edge) {a, head[b], c}; head[b] = cnt;
}

int l[maxn], r[maxn], w[maxn], rnk[maxn];
bool yes[maxn];
inline bool cmp(int a, int b) {return w[a] < w[b];}

int f[maxn];
int find(int x) {return (x == f[x] ? x : (f[x] = find(f[x])));}
int n, m;
long long ans;
#define M 18
int fa[M][maxn], S[M][maxn], dep[maxn];
inline int max(int a, int b) {return a > b ? a : b;}
void dfs(int u) {
	for (int i = 1; i < M; i++) {
		fa[i][u] = fa[i - 1][fa[i - 1][u]];
		S[i][u] = max(S[i - 1][u], S[i - 1][fa[i - 1][u]]);
	}
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if (v != fa[0][u]) {
			fa[0][v] = u;
			dep[v] = dep[u] + 1;
			S[0][v] = e[i].w;
			dfs(v);
		}
	}
}
inline ask(int x, int y) {
	int res = 0;
	if (dep[x] < dep[y]) std::swap(x, y);
	for (int i = dep[x] - dep[y]; i; i &= i - 1) res = max(res, S[__builtin_ctz(i)][x]), x = fa[__builtin_ctz(i)][x];
	if (x == y) return res;
	for (int i = M - 1; ~i; i--) if (fa[i][x] != fa[i][y]) {
		res = max(res, max(S[i][x], S[i][y]));
		x = fa[i][x], y = fa[i][y];
	}
	return max(res, max(S[0][x], S[0][y]));
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i++) {
		scanf("%d%d%d", l + i, r + i, w + i);
		rnk[i] = i;
	}
	for (int i = 1; i <= n; i++) f[i] = i;
	std::sort(rnk, rnk + m, cmp);
	for (int j = 0, i, lastnum = n - 1; j < m && lastnum; j++) {
		i = rnk[j];
		int u = find(l[i]), v = find(r[i]);
		if (u != v) {
			add(l[i], r[i], w[i]);
			yes[i] = true;
			f[u] = v;
			lastnum--;
			ans += w[i];
		}
	}
	dep[1] = 1;
	dfs(1);
	for (int i = 0; i < m; i++) {
		if (yes[i]) printf("%lld
", ans);
		else printf("%lld
", ans - ask(l[i], r[i]) + w[i]);
	}
	return 0;
}

  

以上是关于[CF609E]Minimum spanning tree for each edge的主要内容,如果未能解决你的问题,请参考以下文章

cf 609E.Minimum spanning tree for each edge

CF609E. Minimum spanning tree for each edge

代码源 Div1 - 109#454. Minimum Or Spanning Tree(最小生成树,边权按位或,贪心,并查集) CF1624G

代码源 Div1 - 109#454. Minimum Or Spanning Tree(最小生成树,边权按位或,贪心,并查集) CF1624G

从特定的起始顶点提升 prim_minimum_spanning_tree

Minimum Spanning Tree