zoukankan      html  css  js  c++  java
  • [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;
    }
    

      

  • 相关阅读:
    HDU 4492 Mystery (水题)
    UVA 10480 Sabotage (最大流)
    POJ 2446 Chessboard (二分匹配)
    VS2008下用MFC 的MSComm控件编写串口程序
    退役了~~~
    STL Algorithms 之 unique
    cocos2d中CCCallFuncND传参数的注意事项
    好太太晾衣架市场价格表(仅供参考)
    Linux VNC黑屏(转)
    C++ TinyXml操作(含源码下载)
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10340017.html
Copyright © 2011-2022 走看看