[CF1108F]MST Unification

题目大意:给一张$n(nleqslant2 imes10^5)$个点$m(mleqslant2 imes10^5)$条边的无向带权图,定义一次操作为把一条边边权加一,求要使最小生成树唯一的最少操作数。

题解:先求一个最小生成树,对于任意一条不在最小生成树上的边,只有当它连上后形成的环上有和它边权相同的边时,最小生成树才是不唯一的,这是就要把这条边边权加一,并且,相同的那一条边一定是这个环上边权最大的边。所以可以用树上倍增求这条边,然后比较一下就行了。

卡点:树上倍增多处写错

C++ Code:

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

int head[maxn], cnt;
struct Edge {
	int to, nxt, w;
	inline bool operator < (const Edge &rhs) const {
		return w < rhs.w;
	}
} e[maxn << 1], E[maxn];
inline void addedge(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 n, m;
int f[maxn];
int find(int x) { return x == f[x] ? x : (f[x] = find(f[x])); }
bool used[maxn];

#define M 17
int fa[maxn][M + 1], Mx[maxn][M + 1], dep[maxn];
void dfs(int u) {
	for (int i = 1; i <= M; ++i) {
		fa[u][i] = fa[fa[u][i - 1]][i - 1];
		Mx[u][i] = std::max(Mx[u][i - 1], Mx[fa[u][i - 1]][i - 1]);
	}
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if (v != *fa[u]) {
			*fa[v] = u;
			*Mx[v] = e[i].w;
			dep[v] = dep[u] + 1;
			dfs(v);
		}
	}
}
#define chkmin(x, i) res = std::max(res, Mx[x][i]), x = fa[x][i]
inline int calc(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) chkmin(x, __builtin_ctz(i));
	if (x == y) return res;
	for (int i = M; ~i; --i) if (fa[x][i] != fa[y][i]) chkmin(x, i), chkmin(y, i);
	return std::max(res, std::max(*Mx[x], *Mx[y]));
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; ++i) scanf("%d%d%d", &E[i].to, &E[i].nxt, &E[i].w);
	std::sort(E, E + m);
	for (int i = 1; i <= n; ++i) f[i] = i;
	{
		int num = n - 1;
		for (int i = 0; i < m && num; ++i) {
			int u = E[i].to, v = E[i].nxt, x = find(u), y = find(v);
			if (x != y) {
				f[x] = y;
				--num;
				used[i] = true;
				addedge(u, v, E[i].w);
			}
		}
	}
	dfs(1);
	int ans = 0;
	for (int i = 0; i < m; ++i) if (!used[i]) ans += E[i].w == calc(E[i].to, E[i].nxt);
	printf("%d
", ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/10335626.html