• [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;
    }
    

      

  • 相关阅读:
    【转】很全的TeeChart for .NET中文教程
    对比两个flash金融图表Stock Chart vs AnyStock
    FusionCharts实例大全
    [译]金融图表AnyStock的9个使用技巧
    看懂SqlServer查询计划
    怎样修改MySQL的默认编码
    VS2003+自带水晶报表的打包部署(CS方式)
    ADO.NET 连接池理解
    临时表 & 表变量
    Eclipse 快捷键介绍
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10340017.html
Copyright © 2020-2023  润新知