Description

给定 \(n\) 个点,每个点有点权,连结两个点花费的代价为两点的点权和。另外有 \(m\) 条特殊边,参数为 \(x,y,z\)。意为如果你选择这条边,就可以花费 \(z\) 的代价将点 \(x\) 和点 \(y\) 连结起来,当然你也可以不选择这条边。求使整个图联通的最小代价

Input

第一行是两个整数,分别是点数 \(n\) 和特殊边的数量 \(m\)

下面一行 \(n\) 个数,第 \(i\) 个数代表点 \(i\) 的点权

下面 \(m\) 行,每行三个数 \(x,y,z\),代表一条特殊边

Output

输出一行一个整数,最小代价

Hint

\(1~\leq~n~\leq~2~\times~10^5~,0~\leq~m~\leq~2~\times~10^5\)

设第 \(i\) 个点的点权为 \(a_i\),第 \(j\) 条特殊边的边权为 \(z_j\),保证

\(1~\leq~a_i,z_j~\leq~10^{12}\)

保证特殊边的参数 \(x~\neq~y\)

Solution

显然这个题目是要求一个 MST (最小生成树),但是 \(O(n^2)\) 建图显然不可取。

我们考虑克鲁斯卡尔算法的本质:

有若干个联通块,每次寻找联通块间权值最小的边将之连结。

考虑对于本题来说,在不考虑特殊边的情况下,连结两个联通块,显然要分别选择两个联通块内点权最小的点连结。于是我们对每个集合维护点权最小的点,每次取出点权前两小的集合进行连边即可。维护点权前两小的集合显然可以用一个堆做。

考虑有特殊边怎么办:

我们把特殊边排序,每次比较当前的特殊边的权值小还是前两个联通块的点权小,选择更小的合并。

注意处理一下当前选出的两个点在一个集合中的情况。

因为一共要做 \(O(n)\) 次,每次会有 \(O(1)\) 次对堆的插入和删除操作,于是复杂度 \(O(n \log n)\)

Code

#include <cstdio>
#include <queue>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 200010;
const int maxm = 400010; struct Edge {
int from, to;
ll v;
inline bool operator<(const Edge &_others) const {
return this->v < _others.v;
}
};
Edge edge[maxm]; int n, m;
int ufs[maxn], vec[maxn], rk[maxn];
ll ans;
ll MU[maxn]; struct Zay {
int id;
ll v;
inline bool operator<(const Zay &_others) const {
return this->v > _others.v;
}
};
std::priority_queue<Zay>Q; int find(ci x) {return ufs[x] == x ? x : ufs[x] = find(ufs[x]);} int main() {
freopen("1.in", "r", stdin);
qr(n); qr(m);
for (rg int i = 1; i <= n; ++i) qr(MU[i]);
for (rg int i = 1; i <= m; ++i) {
qr(edge[i].from); qr(edge[i].to); qr(edge[i].v);
}
std::sort(edge + 1, edge + 1 + m);
edge[m + 1].v = 1ll << 62;
for (rg int i = 1; i <= n; ++i) ufs[i] = i, vec[i] = i, rk[i] = 1, Q.push((Zay){i, MU[i]});
for (rg int i = 1, cur = 1; i < n; ++i) {
while ((cur <= m) && (find(edge[cur].from) == find(edge[cur].to))) ++cur;
Zay t1 = Q.top(); Q.pop(); Zay t2 = Q.top(); Q.pop();
while (find(t1.id) == find(t2.id)) {t2 = Q.top(); Q.pop();}
if ((t1.v + t2.v) <= edge[cur].v) {
int fa = find(t1.id), fb = find(t2.id);
ans += t1.v + t2.v;
if (rk[fa] < rk[fb]) ufs[fb] = fa;
else if (rk[fa] > rk[fb]) ufs[fa] = fb;
else ufs[fa] = fb, ++rk[fb];
Q.push((Zay){find(fa), t1.v});
vec[find(fa)] = vec[fa];
} else {
int fa = find(edge[cur].from), fb = find(edge[cur].to);
ans += edge[cur].v;
if (rk[fa] < rk[fb]) ufs[fb] = fa;
else if (rk[fa] > rk[fb]) ufs[fa] = fb;
else ufs[fa] = fb, ++rk[fb];
Q.push((Zay){find(fa), MU[vec[fa]]});
vec[find(fa)] = vec[fa];
Q.push(t1); Q.push(t2);
}
}
qw(ans, '\n', true);
return 0;
}

【生成树,堆】【CF1095F】 Make It Connected的更多相关文章

  1. [CF1095F]Make It Connected

    题目大意:给你$n(n\leqslant2\times10^5)$个点和$m(m\leqslant2\times10^5)$条边,第$i$个点点权为$a_i$.连接$u,v$两个点的代价为$a_u+a ...

  2. 【CF1095F】 Make It Connected(最小生成树)

    题目链接 如果没有特殊边的话显然答案就是权值最小的点向其他所有点连边. 所以把特殊边和权值最小的点向其他点连的边丢一起跑最小生成树就行了. #include <cstdio> #inclu ...

  3. 题解 CF1095F 【Make It Connected】

    题意简述 \(n\)( \(1≤n≤2×10^5\) )个点,每个点 \(i\) 有一个点权 \(a_i\) ( \(1≤a_i≤2×10^{12}\) ),将两个点 \(i\),\(j\) 直接相连 ...

  4. POJ 2728 Desert King 最优比率生成树

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20978   Accepted: 5898 [Des ...

  5. POJ 2728 Desert King(最优比例生成树 二分 | Dinkelbach迭代法)

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 25310   Accepted: 7022 Desc ...

  6. [POJ2728] Desert King 解题报告(最优比率生成树)

    题目描述: David the Great has just become the king of a desert country. To win the respect of his people ...

  7. PAT树_层序遍历叶节点、中序建树后序输出、AVL树的根、二叉树路径存在性判定、奇妙的完全二叉搜索树、最小堆路径、文件路由

    03-树1. List Leaves (25) Given a tree, you are supposed to list all the leaves in the order of top do ...

  8. ACM:Pseudoforest-并查集-最大生成树-解题报

    Pseudoforest Time Limit:5000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status ...

  9. hdu 3367 Pseudoforest(最大生成树)

    Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

随机推荐

  1. 令自己的本地ip可以被外网访问

    https://www.ngrok.cc/_book/general/open.html

  2. mnist手写数字识别(Logistic回归)

    import numpy as np from sklearn.neural_network import MLPClassifier from sklearn.linear_model import ...

  3. Zabbix部署-LNMP环境

    原文发表于cu:2016-05-05 参考文档: LNMP安装:http://www.osyunwei.com/archives/7891.html 一.环境 Server:CentOS-7-x86_ ...

  4. Laxcus大数据操作系统单机集群版

    Laxcus大数据管理系统是我们Laxcus大数据实验室历时5年,全体系全功能设计研发的大数据产品,目前的最新版本是2.1版本.从三年前的1.0版本开始,Laxcus大数据系统投入到多个大数据和云计算 ...

  5. LeetCode--147.对链表进行插入排序

    题目描述: 插入排序的动画演示如上.从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示). 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中. 插入排序算法 ...

  6. [T-ARA][너 때문에 미쳐][因为你而疯了]

    歌词来源:http://music.163.com/#/song?id=5402880 作曲 : 赵英秀/김태현 [作曲 : 赵英秀/k/gim-Tae-hyeon] 作词 : 辉星 [作词 : 辉星 ...

  7. Amazon 成功的秘訣是…

    從任何的標準去看,今日的 Amazon,都是一家超級成功的企業 — 它的線上書城和其他 B2C 電子商務業務,全球第一,年營業額超過 200 億美金.它的 AWS (Amazon Web Servic ...

  8. 福大软工1816 ·软工之404NoteFound团队选题报告

    目录 NABCD分析引用 N(Need,需求): A(Approach,做法): B(Benefit,好处): C(Competitors,竞争): D(Delivery,交付): 初期 中期 个人贡 ...

  9. 关于解决乱码问题的一点探索之二(涉及Unicode(utf-16)和GBK)

        在上篇日志中(链接),我们讨论了utf-8编码和GBK编码之间转化的乱码问题,这一篇我们讨论Unicode(utf-16编码方式)与GBK编码之间转换的乱码问题.     在Windows系统 ...

  10. 【Biocode】产生三行的seq+01序列

    代码说明: sequence.txt与site.txt整合 如下图: sequence.txt: site.txt: 整理之后如下: 蛋白质序列中发生翻译后修饰的位置标记为“1”,其他的位置标记为“0 ...