[CF1095F]Make It Connected

Posted memory-of-winter

tags:

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

题目大意:给你$n(nleqslant2 imes10^5)$个点和$m(mleqslant2 imes10^5)$条边,第$i$个点点权为$a_i$。连接$u,v$两个点的代价为$a_u+a_v$或者一条连接$u,v$的边的边权。问连通的最小代价

题解:发现若不考虑特殊边,一定是点权最小的点连向其他点。于是建出由点权最小的点连向其他各点的边,边权为两点点权和。与特殊边一起跑最小生成树即可。

卡点:

 

C++ Code:

#include <algorithm>
#include <cstdio>
#define maxn 200010
int n, m;
int l[maxn << 1], r[maxn << 1], rnk[maxn << 1];
long long ans, a[maxn], w[maxn << 1];

int f[maxn];
int find(int x) { return x == f[x] ? x : (f[x] = find(f[x])); }

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", a + i);
		rnk[i] = f[i] = i;
	}
	std::sort(rnk + 1, rnk + n + 1, [] (int x, int y) { return a[x] < a[y]; });
	const long long base = a[rnk[1]];
	const int L = rnk[1];
	for (int i = 1; i < n; ++i) {
		w[i] = a[rnk[i + 1]] + base;
		l[i] = L, r[i] = rnk[i + 1];
		rnk[i] = i;
	}
	for (int i = n; i < n + m; ++i) {
		scanf("%d%d%lld", l + i, r + i, w + i);
		rnk[i] = i;
	}
	std::sort(rnk + 1, rnk + n + m, [] (int x, int y) { return w[x] < w[y]; });
	int num = n - 1;
	for (int i = 1, u, v; i < n + m && num; ++i) {
		u = find(l[rnk[i]]), v = find(r[rnk[i]]);
		if (u != v) {
			f[u] = v;
			ans += w[rnk[i]];
			--num;
		}
	}
	printf("%lld
", ans);
	return 0;
}

  

以上是关于[CF1095F]Make It Connected的主要内容,如果未能解决你的问题,请参考以下文章

Make It Connected CodeForces - 1095F (建图+最小生成树)

CF1095F——两种贪心解法的内在一致性;kruskal

[CF 1043F] Make It One

CF1342F Make It Ascending

CF1342F Make It Ascending

CF1065C Make It Equal