码迷,mamicode.com
首页 > 其他好文 > 详细

[CF1095F]Make It Connected

时间:2019-01-30 23:18:28      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:特殊   connected   一起   题解   题目   连接   cpp   生成树   color   

题目大意:给你$n(n\leqslant2\times10^5)$个点和$m(m\leqslant2\times10^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\n", ans);
	return 0;
}

  

[CF1095F]Make It Connected

标签:特殊   connected   一起   题解   题目   连接   cpp   生成树   color   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!