分三步,输入,排序,并查集连接n次
using ll = long long;
constexpr int N = 2e5 + 5;
constexpr int M = 5e5 + 5;
ll ans, sum, n, m;
struct DSU {
std::vector<int> f, siz;
DSU() {}
DSU(int n) {
init(n);
}
void init(int n) {
f.resize(n);
std::iota(f.begin(), f.end(), 0);
siz.assign(n, 1);
}
int find(int x) {
while (x != f[x]) {
x = f[x] = f[f[x]];
}
return x;
}
bool merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y) return false;
siz[x] += siz[y];
f[y] = x;
return true;
}
int size(int x) {
return siz[find(x)];
}
};
DSU dsu(N);
struct edge {
ll from, to, value;
};
std::vector<edge> e(M*2);
void Kruskal() {
ll tot = 0;
//按值的大小排序
std::sort(e.begin() + 1, e.begin() + 1 + m, [&](const edge& x, const edge& y) {
return x.value < y.value;
});
//枚举边值
for (int i = 1; i <= m; i++) {
//连接n次
if (dsu.merge(e[i].to, e[i].from)) {
tot++;
ans += e[i].value;
}
if (tot == n) break;
}
}
int main() {
//输入
std::cin >> n >> m;
for (int i = 1; i <= m; i++) {
std::cin >> e[i].from >> e[i].to >> e[i].value;
}
Kruskal();
//打印答案
std::cout << ans << '\n';
return 0;
}
这道题增加了一个连通性的判断
//改一下数据,增加一个判断连通性
constexpr int N = 5000 + 5;
constexpr int M = 2e5 + 5;
int main() {
std::cin >> n >> m;
for (int i = 1; i <= m; i++) {
std::cin >> e[i].from >> e[i].to >> e[i].value;
}
Kruskal();
//连接完
for (int i = 1; i <= m; i++) {
dsu.merge(e[i].to, e[i].from);
}
//枚举节点看父节点是否相同
bool connected = true;
for (int i = 1; i <= n; ++i) {
if (dsu.find(i) != dsu.find(1)) {
connected = false;
break;
}
}
if (connected) {
std::cout << ans << '\n';
}
else {
std::cout << "orz" << '\n';
}
return 0;
}